Add schemes (#71) * Move br + cbt to schemes/tfhe * refactor blind rotation * refactor circuit bootstrapping * renamed exec -> prepared
jump to
@@ -564,6 +564,17 @@ "rand_distr",
] [[package]] +name = "schemes" +version = "0.1.0" +dependencies = [ + "backend", + "byteorder", + "core", + "itertools 0.14.0", + "sampling", +] + +[[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1,5 +1,5 @@
[workspace] -members = ["backend", "core", "sampling", "utils"] +members = ["backend", "core", "sampling", "utils", "schemes"] resolver = "3" [workspace.dependencies]@@ -11,4 +11,4 @@ rand_distr = "0.5.1"
itertools = "0.14.0" criterion = "0.7.0" byteorder = "1.5.0" -zstd = "0.13.3"+zstd = "0.13.3"
@@ -115,12 +115,12 @@ pub(crate) data: ScalarZnx<D>,
pub(crate) dist: Distribution, } - pub struct GLWESecretExec<D: Data, B: Backend> { + pub struct GLWESecrecPrepared<D: Data, B: Backend> { pub(crate) data: SvpPPol<D, B>, pub(crate) dist: Distribution, } - impl<D: DataMut, B: Backend> GLWESecretExec<D, B> { + impl<D: DataMut, B: Backend> GLWESecretPrepared<D, B> { pub fn prepare<O>(&mut self, module: &Module<B>, sk: &GLWESecret<O>) where O: DataRef,
@@ -3,8 +3,7 @@ hal::{
api::{ ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPrepare, VecZnxAddNormal, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallBInplace, - VecZnxDecodeVeci64, VecZnxDftAlloc, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigTmpA, VecZnxEncodeVeci64, - VecZnxFillUniform, VecZnxNormalizeInplace, ZnxInfos, + VecZnxDftAlloc, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigTmpA, VecZnxFillUniform, VecZnxNormalizeInplace, ZnxInfos, }, layouts::{Module, ScalarZnx, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft}, },@@ -73,7 +72,7 @@ );
let mut want: Vec<i64> = vec![0; n]; want.iter_mut() .for_each(|x| *x = source.next_u64n(16, 15) as i64); - module.encode_vec_i64(basek, &mut m, 0, log_scale, &want, 4); + m.encode_vec_i64(basek, 0, log_scale, &want, 4); module.vec_znx_normalize_inplace(basek, &mut m, 0, scratch.borrow()); // m - BIG(ct[1] * s)@@ -132,8 +131,7 @@ module.vec_znx_big_normalize(basek, &mut res, 0, &buf_big, 0, scratch.borrow());
// have = m * 2^{log_scale} + e let mut have: Vec<i64> = vec![i64::default(); n]; - module.decode_vec_i64(basek, &mut res, 0, ct_size * basek, &mut have); - + res.decode_vec_i64(basek, 0, ct_size * basek, &mut have); let scale: f64 = (1 << (res.size() * basek - log_scale)) as f64; izip!(want.iter(), have.iter()) .enumerate()
@@ -1,5 +1,4 @@
use rand_distr::Distribution; -use rug::Float; use sampling::source::Source; use crate::hal::layouts::{Backend, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef};@@ -198,13 +197,6 @@ R: VecZnxToMut,
A: VecZnxToRef; } -pub trait VecZnxStd { - /// Returns the standard devaition of the i-th polynomial. - fn vec_znx_std<A>(&self, basek: usize, a: &A, a_col: usize) -> f64 - where - A: VecZnxToRef; -} - pub trait VecZnxFillUniform { /// Fills the first `size` size with uniform values in \[-2^{basek-1}, 2^{basek-1}\] fn vec_znx_fill_uniform<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, source: &mut Source)@@ -269,75 +261,3 @@ bound: f64,
) where R: VecZnxToMut; } - -pub trait VecZnxEncodeVeci64 { - /// encode a vector of i64 on the receiver. - /// - /// # Arguments - /// - /// * `col_i`: the index of the poly where to encode the data. - /// * `basek`: base two negative logarithm decomposition of the receiver. - /// * `k`: base two negative logarithm of the scaling of the data. - /// * `data`: data to encode on the receiver. - /// * `log_max`: base two logarithm of the infinity norm of the input data. - fn encode_vec_i64<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, data: &[i64], log_max: usize) - where - R: VecZnxToMut; -} - -pub trait VecZnxEncodeCoeffsi64 { - /// encodes a single i64 on the receiver at the given index. - /// - /// # Arguments - /// - /// * `res_col`: the index of the poly where to encode the data. - /// * `basek`: base two negative logarithm decomposition of the receiver. - /// * `k`: base two negative logarithm of the scaling of the data. - /// * `i`: index of the coefficient on which to encode the data. - /// * `data`: data to encode on the receiver. - /// * `log_max`: base two logarithm of the infinity norm of the input data. - fn encode_coeff_i64<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, i: usize, data: i64, log_max: usize) - where - R: VecZnxToMut; -} - -pub trait VecZnxDecodeVeci64 { - /// decode a vector of i64 from the receiver. - /// - /// # Arguments - /// - /// * `res_col`: the index of the poly where to encode the data. - /// * `basek`: base two negative logarithm decomposition of the receiver. - /// * `k`: base two logarithm of the scaling of the data. - /// * `data`: data to decode from the receiver. - fn decode_vec_i64<R>(&self, basek: usize, res: &R, res_col: usize, k: usize, data: &mut [i64]) - where - R: VecZnxToRef; -} - -pub trait VecZnxDecodeCoeffsi64 { - /// decode a single of i64 from the receiver at the given index. - /// - /// # Arguments - /// - /// * `res_col`: the index of the poly where to encode the data. - /// * `basek`: base two negative logarithm decomposition of the receiver. - /// * `k`: base two negative logarithm of the scaling of the data. - /// * `i`: index of the coefficient to decode. - /// * `data`: data to decode from the receiver. - fn decode_coeff_i64<R>(&self, basek: usize, res: &R, res_col: usize, k: usize, i: usize) -> i64 - where - R: VecZnxToRef; -} - -pub trait VecZnxDecodeVecFloat { - /// decode a vector of Float from the receiver. - /// - /// # Arguments - /// * `col_i`: the index of the poly where to encode the data. - /// * `basek`: base two negative logarithm decomposition of the receiver. - /// * `data`: data to decode from the receiver. - fn decode_vec_float<R>(&self, basek: usize, res: &R, col_i: usize, data: &mut [Float]) - where - R: VecZnxToRef; -}
@@ -3,22 +3,19 @@
use crate::hal::{ api::{ VecZnxAdd, VecZnxAddDistF64, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, - VecZnxAutomorphismInplace, VecZnxCopy, VecZnxDecodeCoeffsi64, VecZnxDecodeVecFloat, VecZnxDecodeVeci64, - VecZnxEncodeCoeffsi64, VecZnxEncodeVeci64, VecZnxFillDistF64, VecZnxFillNormal, VecZnxFillUniform, VecZnxLshInplace, + VecZnxAutomorphismInplace, VecZnxCopy, VecZnxFillDistF64, VecZnxFillNormal, VecZnxFillUniform, VecZnxLshInplace, VecZnxMerge, VecZnxMulXpMinusOne, VecZnxMulXpMinusOneInplace, VecZnxNegate, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSplit, - VecZnxStd, VecZnxSub, VecZnxSubABInplace, VecZnxSubBAInplace, VecZnxSubScalarInplace, VecZnxSwithcDegree, + VecZnxSub, VecZnxSubABInplace, VecZnxSubBAInplace, VecZnxSubScalarInplace, VecZnxSwithcDegree, }, layouts::{Backend, Module, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef}, oep::{ VecZnxAddDistF64Impl, VecZnxAddImpl, VecZnxAddInplaceImpl, VecZnxAddNormalImpl, VecZnxAddScalarInplaceImpl, - VecZnxAutomorphismImpl, VecZnxAutomorphismInplaceImpl, VecZnxCopyImpl, VecZnxDecodeCoeffsi64Impl, - VecZnxDecodeVecFloatImpl, VecZnxDecodeVeci64Impl, VecZnxEncodeCoeffsi64Impl, VecZnxEncodeVeci64Impl, - VecZnxFillDistF64Impl, VecZnxFillNormalImpl, VecZnxFillUniformImpl, VecZnxLshInplaceImpl, VecZnxMergeImpl, - VecZnxMulXpMinusOneImpl, VecZnxMulXpMinusOneInplaceImpl, VecZnxNegateImpl, VecZnxNegateInplaceImpl, VecZnxNormalizeImpl, - VecZnxNormalizeInplaceImpl, VecZnxNormalizeTmpBytesImpl, VecZnxRotateImpl, VecZnxRotateInplaceImpl, VecZnxRshInplaceImpl, - VecZnxSplitImpl, VecZnxStdImpl, VecZnxSubABInplaceImpl, VecZnxSubBAInplaceImpl, VecZnxSubImpl, - VecZnxSubScalarInplaceImpl, VecZnxSwithcDegreeImpl, + VecZnxAutomorphismImpl, VecZnxAutomorphismInplaceImpl, VecZnxCopyImpl, VecZnxFillDistF64Impl, VecZnxFillNormalImpl, + VecZnxFillUniformImpl, VecZnxLshInplaceImpl, VecZnxMergeImpl, VecZnxMulXpMinusOneImpl, VecZnxMulXpMinusOneInplaceImpl, + VecZnxNegateImpl, VecZnxNegateInplaceImpl, VecZnxNormalizeImpl, VecZnxNormalizeInplaceImpl, VecZnxNormalizeTmpBytesImpl, + VecZnxRotateImpl, VecZnxRotateInplaceImpl, VecZnxRshInplaceImpl, VecZnxSplitImpl, VecZnxSubABInplaceImpl, + VecZnxSubBAInplaceImpl, VecZnxSubImpl, VecZnxSubScalarInplaceImpl, VecZnxSwithcDegreeImpl, }, };@@ -325,18 +322,6 @@ B::vec_znx_copy_impl(self, res, res_col, a, a_col)
} } -impl<B> VecZnxStd for Module<B> -where - B: Backend + VecZnxStdImpl<B>, -{ - fn vec_znx_std<A>(&self, basek: usize, a: &A, a_col: usize) -> f64 - where - A: VecZnxToRef, - { - B::vec_znx_std_impl(self, basek, a, a_col) - } -} - impl<B> VecZnxFillUniform for Module<B> where B: Backend + VecZnxFillUniformImpl<B>,@@ -428,63 +413,3 @@ {
B::vec_znx_add_normal_impl(self, basek, res, res_col, k, source, sigma, bound); } } - -impl<B> VecZnxEncodeVeci64 for Module<B> -where - B: Backend + VecZnxEncodeVeci64Impl<B>, -{ - fn encode_vec_i64<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, data: &[i64], log_max: usize) - where - R: VecZnxToMut, - { - B::encode_vec_i64_impl(self, basek, res, res_col, k, data, log_max); - } -} - -impl<B> VecZnxEncodeCoeffsi64 for Module<B> -where - B: Backend + VecZnxEncodeCoeffsi64Impl<B>, -{ - fn encode_coeff_i64<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, i: usize, data: i64, log_max: usize) - where - R: VecZnxToMut, - { - B::encode_coeff_i64_impl(self, basek, res, res_col, k, i, data, log_max); - } -} - -impl<B> VecZnxDecodeVeci64 for Module<B> -where - B: Backend + VecZnxDecodeVeci64Impl<B>, -{ - fn decode_vec_i64<R>(&self, basek: usize, res: &R, res_col: usize, k: usize, data: &mut [i64]) - where - R: VecZnxToRef, - { - B::decode_vec_i64_impl(self, basek, res, res_col, k, data); - } -} - -impl<B> VecZnxDecodeCoeffsi64 for Module<B> -where - B: Backend + VecZnxDecodeCoeffsi64Impl<B>, -{ - fn decode_coeff_i64<R>(&self, basek: usize, res: &R, res_col: usize, k: usize, i: usize) -> i64 - where - R: VecZnxToRef, - { - B::decode_coeff_i64_impl(self, basek, res, res_col, k, i) - } -} - -impl<B> VecZnxDecodeVecFloat for Module<B> -where - B: Backend + VecZnxDecodeVecFloatImpl<B>, -{ - fn decode_vec_float<R>(&self, basek: usize, res: &R, col_i: usize, data: &mut [rug::Float]) - where - R: VecZnxToRef, - { - B::decode_vec_float_impl(self, basek, res, col_i, data); - } -}
@@ -0,0 +1,204 @@
+use itertools::izip; +use rug::{Assign, Float}; + +use crate::hal::{ + api::{ZnxInfos, ZnxView, ZnxViewMut, ZnxZero}, + layouts::{DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef}, +}; + +impl<D: DataMut> VecZnx<D> { + pub fn encode_vec_i64(&mut self, basek: usize, col: usize, k: usize, data: &[i64], log_max: usize) { + let size: usize = k.div_ceil(basek); + + #[cfg(debug_assertions)] + { + let a: VecZnx<&mut [u8]> = self.to_mut(); + assert!( + size <= a.size(), + "invalid argument k: k.div_ceil(basek)={} > a.size()={}", + size, + a.size() + ); + assert!(col < a.cols()); + assert!(data.len() <= a.n()) + } + + let data_len: usize = data.len(); + let mut a: VecZnx<&mut [u8]> = self.to_mut(); + let k_rem: usize = basek - (k % basek); + + // Zeroes coefficients of the i-th column + (0..a.size()).for_each(|i| { + a.zero_at(col, i); + }); + + // If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy + // values on the last limb. + // Else we decompose values base2k. + if log_max + k_rem < 63 || k_rem == basek { + a.at_mut(col, size - 1)[..data_len].copy_from_slice(&data[..data_len]); + } else { + let mask: i64 = (1 << basek) - 1; + let steps: usize = size.min(log_max.div_ceil(basek)); + (size - steps..size) + .rev() + .enumerate() + .for_each(|(i, i_rev)| { + let shift: usize = i * basek; + izip!(a.at_mut(col, i_rev).iter_mut(), data.iter()).for_each(|(y, x)| *y = (x >> shift) & mask); + }) + } + + // Case where self.prec % self.k != 0. + if k_rem != basek { + let steps: usize = size.min(log_max.div_ceil(basek)); + (size - steps..size).rev().for_each(|i| { + a.at_mut(col, i)[..data_len] + .iter_mut() + .for_each(|x| *x <<= k_rem); + }) + } + } + + pub fn encode_coeff_i64(&mut self, basek: usize, col: usize, k: usize, idx: usize, data: i64, log_max: usize) { + let size: usize = k.div_ceil(basek); + + #[cfg(debug_assertions)] + { + let a: VecZnx<&mut [u8]> = self.to_mut(); + assert!(idx < a.n()); + assert!( + size <= a.size(), + "invalid argument k: k.div_ceil(basek)={} > a.size()={}", + size, + a.size() + ); + assert!(col < a.cols()); + } + + let k_rem: usize = basek - (k % basek); + let mut a: VecZnx<&mut [u8]> = self.to_mut(); + (0..a.size()).for_each(|j| a.at_mut(col, j)[idx] = 0); + + // If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy + // values on the last limb. + // Else we decompose values base2k. + if log_max + k_rem < 63 || k_rem == basek { + a.at_mut(col, size - 1)[idx] = data; + } else { + let mask: i64 = (1 << basek) - 1; + let steps: usize = size.min(log_max.div_ceil(basek)); + (size - steps..size) + .rev() + .enumerate() + .for_each(|(j, j_rev)| { + a.at_mut(col, j_rev)[idx] = (data >> (j * basek)) & mask; + }) + } + + // Case where prec % k != 0. + if k_rem != basek { + let steps: usize = size.min(log_max.div_ceil(basek)); + (size - steps..size).rev().for_each(|j| { + a.at_mut(col, j)[idx] <<= k_rem; + }) + } + } +} + +impl<D: DataRef> VecZnx<D> { + pub fn decode_vec_i64(&self, basek: usize, col: usize, k: usize, data: &mut [i64]) { + let size: usize = k.div_ceil(basek); + #[cfg(debug_assertions)] + { + let a: VecZnx<&[u8]> = self.to_ref(); + assert!( + data.len() >= a.n(), + "invalid data: data.len()={} < a.n()={}", + data.len(), + a.n() + ); + assert!(col < a.cols()); + } + + let a: VecZnx<&[u8]> = self.to_ref(); + data.copy_from_slice(a.at(col, 0)); + let rem: usize = basek - (k % basek); + if k < basek { + data.iter_mut().for_each(|x| *x >>= rem); + } else { + (1..size).for_each(|i| { + if i == size - 1 && rem != basek { + let k_rem: usize = basek - rem; + izip!(a.at(col, i).iter(), data.iter_mut()).for_each(|(x, y)| { + *y = (*y << k_rem) + (x >> rem); + }); + } else { + izip!(a.at(col, i).iter(), data.iter_mut()).for_each(|(x, y)| { + *y = (*y << basek) + x; + }); + } + }) + } + } + + pub fn decode_coeff_i64(&self, basek: usize, col: usize, k: usize, idx: usize) -> i64 { + #[cfg(debug_assertions)] + { + let a: VecZnx<&[u8]> = self.to_ref(); + assert!(idx < a.n()); + assert!(col < a.cols()) + } + + let a: VecZnx<&[u8]> = self.to_ref(); + let size: usize = k.div_ceil(basek); + let mut res: i64 = 0; + let rem: usize = basek - (k % basek); + (0..size).for_each(|j| { + let x: i64 = a.at(col, j)[idx]; + if j == size - 1 && rem != basek { + let k_rem: usize = basek - rem; + res = (res << k_rem) + (x >> rem); + } else { + res = (res << basek) + x; + } + }); + res + } + + pub fn decode_vec_float(&self, basek: usize, col: usize, data: &mut [Float]) { + #[cfg(debug_assertions)] + { + let a: VecZnx<&[u8]> = self.to_ref(); + assert!( + data.len() >= a.n(), + "invalid data: data.len()={} < a.n()={}", + data.len(), + a.n() + ); + assert!(col < a.cols()); + } + + let a: VecZnx<&[u8]> = self.to_ref(); + let size: usize = a.size(); + let prec: u32 = (basek * size) as u32; + + // 2^{basek} + let base = Float::with_val(prec, (1 << basek) as f64); + + // y[i] = sum x[j][i] * 2^{-basek*j} + (0..size).for_each(|i| { + if i == 0 { + izip!(a.at(col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| { + y.assign(*x); + *y /= &base; + }); + } else { + izip!(a.at(col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| { + *y += Float::with_val(prec, *x); + *y /= &base; + }); + } + }); + } +}
@@ -1,8 +1,10 @@
+mod encoding; mod mat_znx; mod module; mod scalar_znx; mod scratch; mod serialization; +mod stats; mod svp_ppol; mod vec_znx; mod vec_znx_big;
@@ -0,0 +1,32 @@
+use rug::{ + Float, + float::Round, + ops::{AddAssignRound, DivAssignRound, SubAssignRound}, +}; + +use crate::hal::{ + api::ZnxInfos, + layouts::{DataRef, VecZnx}, +}; + +impl<D: DataRef> VecZnx<D> { + pub fn std(&self, basek: usize, col: usize) -> f64 { + let prec: u32 = (self.size() * basek) as u32; + let mut data: Vec<Float> = (0..self.n()).map(|_| Float::with_val(prec, 0)).collect(); + self.decode_vec_float(basek, col, &mut data); + // std = sqrt(sum((xi - avg)^2) / n) + let mut avg: Float = Float::with_val(prec, 0); + data.iter().for_each(|x| { + avg.add_assign_round(x, Round::Nearest); + }); + avg.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest); + data.iter_mut().for_each(|x| { + x.sub_assign_round(&avg, Round::Nearest); + }); + let mut std: Float = Float::with_val(prec, 0); + data.iter().for_each(|x| std += x * x); + std.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest); + std = std.sqrt(); + std.to_f64() + } +}
@@ -1,5 +1,4 @@
use rand_distr::Distribution; -use rug::Float; use sampling::source::Source; use crate::hal::layouts::{Backend, Module, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef};@@ -289,15 +288,6 @@ A: VecZnxToRef;
} /// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See [crate::hal::api::VecZnxStd] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxStdImpl<B: Backend> { - fn vec_znx_std_impl<A>(module: &Module<B>, basek: usize, a: &A, a_col: usize) -> f64 - where - A: VecZnxToRef; -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) /// * See [crate::hal::api::VecZnxFillUniform] for corresponding public API. /// * See [crate::doc::backend_safety] for safety contract. pub unsafe trait VecZnxFillUniformImpl<B: Backend> {@@ -373,68 +363,3 @@ bound: f64,
) where R: VecZnxToMut; } - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See \[TODO\] for reference code. -/// * See [crate::hal::api::VecZnxEncodeVeci64] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxEncodeVeci64Impl<B: Backend> { - fn encode_vec_i64_impl<R>( - module: &Module<B>, - basek: usize, - res: &mut R, - res_col: usize, - k: usize, - data: &[i64], - log_max: usize, - ) where - R: VecZnxToMut; -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See \[TODO\] for reference code. -/// * See [crate::hal::api::VecZnxEncodeCoeffsi64] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxEncodeCoeffsi64Impl<B: Backend> { - fn encode_coeff_i64_impl<R>( - module: &Module<B>, - basek: usize, - res: &mut R, - res_col: usize, - k: usize, - i: usize, - data: i64, - log_max: usize, - ) where - R: VecZnxToMut; -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See \[TODO\] for reference code. -/// * See [crate::hal::api::VecZnxDecodeVeci64] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxDecodeVeci64Impl<B: Backend> { - fn decode_vec_i64_impl<R>(module: &Module<B>, basek: usize, res: &R, res_col: usize, k: usize, data: &mut [i64]) - where - R: VecZnxToRef; -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See \[TODO\] for reference code. -/// * See [crate::hal::api::VecZnxDecodeCoeffsi64] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxDecodeCoeffsi64Impl<B: Backend> { - fn decode_coeff_i64_impl<R>(module: &Module<B>, basek: usize, res: &R, res_col: usize, k: usize, i: usize) -> i64 - where - R: VecZnxToRef; -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See \[TODO\] for reference code. -/// * See [crate::hal::api::VecZnxDecodeVecFloat] for corresponding public API. -/// * See [crate::doc::backend_safety] for safety contract. -pub unsafe trait VecZnxDecodeVecFloatImpl<B: Backend> { - fn decode_vec_float_impl<R>(module: &Module<B>, basek: usize, res: &R, res_col: usize, data: &mut [Float]) - where - R: VecZnxToRef; -}
@@ -0,0 +1,52 @@
+use sampling::source::Source; + +use crate::hal::{ + api::{ZnxInfos, ZnxViewMut}, + layouts::VecZnx, +}; + +pub fn test_vec_znx_encode_vec_i64_lo_norm() { + let n: usize = 32; + let basek: usize = 17; + let size: usize = 5; + let k: usize = size * basek - 5; + let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size); + let mut source: Source = Source::new([0u8; 32]); + let raw: &mut [i64] = a.raw_mut(); + raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64); + (0..a.cols()).for_each(|col_i| { + let mut have: Vec<i64> = vec![i64::default(); n]; + have.iter_mut() + .for_each(|x| *x = (source.next_i64() << 56) >> 56); + a.encode_vec_i64(basek, col_i, k, &have, 10); + let mut want: Vec<i64> = vec![i64::default(); n]; + a.decode_vec_i64(basek, col_i, k, &mut want); + assert_eq!(have, want, "{:?} != {:?}", &have, &want); + }); +} + +pub fn test_vec_znx_encode_vec_i64_hi_norm() { + let n: usize = 32; + let basek: usize = 17; + let size: usize = 5; + for k in [1, basek / 2, size * basek - 5] { + let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size); + let mut source = Source::new([0u8; 32]); + let raw: &mut [i64] = a.raw_mut(); + raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64); + (0..a.cols()).for_each(|col_i| { + let mut have: Vec<i64> = vec![i64::default(); n]; + have.iter_mut().for_each(|x| { + if k < 64 { + *x = source.next_u64n(1 << k, (1 << k) - 1) as i64; + } else { + *x = source.next_i64(); + } + }); + a.encode_vec_i64(basek, col_i, k, &have, 63); + let mut want: Vec<i64> = vec![i64::default(); n]; + a.decode_vec_i64(basek, col_i, k, &mut want); + assert_eq!(have, want, "{:?} != {:?}", &have, &want); + }) + } +}
@@ -1,14 +1,13 @@
-use itertools::izip; use sampling::source::Source; use crate::hal::{ - api::{VecZnxAddNormal, VecZnxDecodeVeci64, VecZnxEncodeVeci64, VecZnxFillUniform, VecZnxStd, ZnxInfos, ZnxView, ZnxViewMut}, + api::{VecZnxAddNormal, VecZnxFillUniform, ZnxView}, layouts::{Backend, Module, VecZnx}, }; pub fn test_vec_znx_fill_uniform<B: Backend>(module: &Module<B>) where - Module<B>: VecZnxFillUniform + VecZnxStd, + Module<B>: VecZnxFillUniform, { let n: usize = module.n(); let basek: usize = 17;@@ -26,7 +25,7 @@ (0..size).for_each(|limb_i| {
assert_eq!(a.at(col_j, limb_i), zero); }) } else { - let std: f64 = module.vec_znx_std(basek, &a, col_i); + let std: f64 = a.std(basek, col_i); assert!( (std - one_12_sqrt).abs() < 0.01, "std={} ~!= {}",@@ -40,7 +39,7 @@ }
pub fn test_vec_znx_add_normal<B: Backend>(module: &Module<B>) where - Module<B>: VecZnxAddNormal + VecZnxStd, + Module<B>: VecZnxAddNormal, { let n: usize = module.n(); let basek: usize = 17;@@ -61,61 +60,9 @@ (0..size).for_each(|limb_i| {
assert_eq!(a.at(col_j, limb_i), zero); }) } else { - let std: f64 = module.vec_znx_std(basek, &a, col_i) * k_f64; + let std: f64 = a.std(basek, col_i) * k_f64; assert!((std - sigma).abs() < 0.1, "std={} ~!= {}", std, sigma); } }) }); } - -pub fn test_vec_znx_encode_vec_i64_lo_norm<B: Backend>(module: &Module<B>) -where - Module<B>: VecZnxEncodeVeci64 + VecZnxDecodeVeci64, -{ - let n: usize = module.n(); - let basek: usize = 17; - let size: usize = 5; - let k: usize = size * basek - 5; - let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size); - let mut source: Source = Source::new([0u8; 32]); - let raw: &mut [i64] = a.raw_mut(); - raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64); - (0..a.cols()).for_each(|col_i| { - let mut have: Vec<i64> = vec![i64::default(); n]; - have.iter_mut() - .for_each(|x| *x = (source.next_i64() << 56) >> 56); - module.encode_vec_i64(basek, &mut a, col_i, k, &have, 10); - let mut want: Vec<i64> = vec![i64::default(); n]; - module.decode_vec_i64(basek, &a, col_i, k, &mut want); - izip!(want, have).for_each(|(a, b)| assert_eq!(a, b, "{} != {}", a, b)); - }); -} - -pub fn test_vec_znx_encode_vec_i64_hi_norm<B: Backend>(module: &Module<B>) -where - Module<B>: VecZnxEncodeVeci64 + VecZnxDecodeVeci64, -{ - let n: usize = module.n(); - let basek: usize = 17; - let size: usize = 5; - for k in [1, basek / 2, size * basek - 5] { - let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size); - let mut source = Source::new([0u8; 32]); - let raw: &mut [i64] = a.raw_mut(); - raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64); - (0..a.cols()).for_each(|col_i| { - let mut have: Vec<i64> = vec![i64::default(); n]; - have.iter_mut().for_each(|x| { - if k < 64 { - *x = source.next_u64n(1 << k, (1 << k) - 1) as i64; - } else { - *x = source.next_i64(); - } - }); - module.encode_vec_i64(basek, &mut a, col_i, k, &have, 63); - let mut want: Vec<i64> = vec![i64::default(); n]; - module.decode_vec_i64(basek, &a, col_i, k, &mut want); - izip!(want, have).for_each(|(a, b)| assert_eq!(a, b, "{} != {}", a, b)); - }) - } -}
@@ -1,2 +1,5 @@
mod generics; pub use generics::*; + +#[cfg(test)] +mod encoding;
@@ -2,10 +2,7 @@ use crate::{
hal::{ api::ModuleNew, layouts::Module, - tests::vec_znx::{ - test_vec_znx_add_normal, test_vec_znx_encode_vec_i64_hi_norm, test_vec_znx_encode_vec_i64_lo_norm, - test_vec_znx_fill_uniform, - }, + tests::vec_znx::{test_vec_znx_add_normal, test_vec_znx_fill_uniform}, }, implementation::cpu_spqlios::FFT64, };@@ -21,15 +18,3 @@ fn test_vec_znx_add_normal_fft64() {
let module: Module<FFT64> = Module::<FFT64>::new(1 << 12); test_vec_znx_add_normal(&module); } - -#[test] -fn test_vec_znx_encode_vec_lo_norm_fft64() { - let module: Module<FFT64> = Module::<FFT64>::new(1 << 8); - test_vec_znx_encode_vec_i64_lo_norm(&module); -} - -#[test] -fn test_vec_znx_encode_vec_hi_norm_fft64() { - let module: Module<FFT64> = Module::<FFT64>::new(1 << 8); - test_vec_znx_encode_vec_i64_hi_norm(&module); -}
@@ -1,29 +1,22 @@
use itertools::izip; use rand_distr::Normal; -use rug::{ - Assign, Float, - float::Round, - ops::{AddAssignRound, DivAssignRound, SubAssignRound}, -}; use sampling::source::Source; use crate::{ hal::{ api::{ - TakeSlice, TakeVecZnx, VecZnxAddDistF64, VecZnxCopy, VecZnxDecodeVecFloat, VecZnxFillDistF64, - VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxSwithcDegree, ZnxInfos, ZnxSliceSize, ZnxView, - ZnxViewMut, ZnxZero, + TakeSlice, TakeVecZnx, VecZnxAddDistF64, VecZnxCopy, VecZnxFillDistF64, VecZnxNormalizeTmpBytes, VecZnxRotate, + VecZnxRotateInplace, VecZnxSwithcDegree, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero, }, layouts::{Backend, Module, ScalarZnx, ScalarZnxToRef, Scratch, VecZnx, VecZnxToMut, VecZnxToRef}, oep::{ VecZnxAddDistF64Impl, VecZnxAddImpl, VecZnxAddInplaceImpl, VecZnxAddNormalImpl, VecZnxAddScalarInplaceImpl, - VecZnxAutomorphismImpl, VecZnxAutomorphismInplaceImpl, VecZnxCopyImpl, VecZnxDecodeCoeffsi64Impl, - VecZnxDecodeVecFloatImpl, VecZnxDecodeVeci64Impl, VecZnxEncodeCoeffsi64Impl, VecZnxEncodeVeci64Impl, - VecZnxFillDistF64Impl, VecZnxFillNormalImpl, VecZnxFillUniformImpl, VecZnxLshInplaceImpl, VecZnxMergeImpl, - VecZnxMulXpMinusOneImpl, VecZnxMulXpMinusOneInplaceImpl, VecZnxNegateImpl, VecZnxNegateInplaceImpl, - VecZnxNormalizeImpl, VecZnxNormalizeInplaceImpl, VecZnxNormalizeTmpBytesImpl, VecZnxRotateImpl, - VecZnxRotateInplaceImpl, VecZnxRshInplaceImpl, VecZnxSplitImpl, VecZnxStdImpl, VecZnxSubABInplaceImpl, - VecZnxSubBAInplaceImpl, VecZnxSubImpl, VecZnxSubScalarInplaceImpl, VecZnxSwithcDegreeImpl, + VecZnxAutomorphismImpl, VecZnxAutomorphismInplaceImpl, VecZnxCopyImpl, VecZnxFillDistF64Impl, VecZnxFillNormalImpl, + VecZnxFillUniformImpl, VecZnxLshInplaceImpl, VecZnxMergeImpl, VecZnxMulXpMinusOneImpl, + VecZnxMulXpMinusOneInplaceImpl, VecZnxNegateImpl, VecZnxNegateInplaceImpl, VecZnxNormalizeImpl, + VecZnxNormalizeInplaceImpl, VecZnxNormalizeTmpBytesImpl, VecZnxRotateImpl, VecZnxRotateInplaceImpl, + VecZnxRshInplaceImpl, VecZnxSplitImpl, VecZnxSubABInplaceImpl, VecZnxSubBAInplaceImpl, VecZnxSubImpl, + VecZnxSubScalarInplaceImpl, VecZnxSwithcDegreeImpl, }, }, implementation::cpu_spqlios::{@@ -857,35 +850,6 @@ res_mut.zero_at(res_col, j);
}) } -unsafe impl<B: Backend> VecZnxStdImpl<B> for B -where - B: CPUAVX, -{ - fn vec_znx_std_impl<A>(module: &Module<B>, basek: usize, a: &A, a_col: usize) -> f64 - where - A: VecZnxToRef, - { - let a: VecZnx<&[u8]> = a.to_ref(); - let prec: u32 = (a.size() * basek) as u32; - let mut data: Vec<Float> = (0..a.n()).map(|_| Float::with_val(prec, 0)).collect(); - module.decode_vec_float(basek, &a, a_col, &mut data); - // std = sqrt(sum((xi - avg)^2) / n) - let mut avg: Float = Float::with_val(prec, 0); - data.iter().for_each(|x| { - avg.add_assign_round(x, Round::Nearest); - }); - avg.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest); - data.iter_mut().for_each(|x| { - x.sub_assign_round(&avg, Round::Nearest); - }); - let mut std: Float = Float::with_val(prec, 0); - data.iter().for_each(|x| std += x * x); - std.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest); - std = std.sqrt(); - std.to_f64() - } -} - unsafe impl<B: Backend> VecZnxFillUniformImpl<B> for B where B: CPUAVX,@@ -1053,251 +1017,3 @@ bound,
); } } - -unsafe impl<B: Backend> VecZnxEncodeVeci64Impl<B> for B -where - B: CPUAVX, -{ - fn encode_vec_i64_impl<R>( - _module: &Module<B>, - basek: usize, - res: &mut R, - res_col: usize, - k: usize, - data: &[i64], - log_max: usize, - ) where - R: VecZnxToMut, - { - let size: usize = k.div_ceil(basek); - - #[cfg(debug_assertions)] - { - let a: VecZnx<&mut [u8]> = res.to_mut(); - assert!( - size <= a.size(), - "invalid argument k: k.div_ceil(basek)={} > a.size()={}", - size, - a.size() - ); - assert!(res_col < a.cols()); - assert!(data.len() <= a.n()) - } - - let data_len: usize = data.len(); - let mut a: VecZnx<&mut [u8]> = res.to_mut(); - let k_rem: usize = basek - (k % basek); - - // Zeroes coefficients of the i-th column - (0..a.size()).for_each(|i| { - a.zero_at(res_col, i); - }); - - // If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy - // values on the last limb. - // Else we decompose values base2k. - if log_max + k_rem < 63 || k_rem == basek { - a.at_mut(res_col, size - 1)[..data_len].copy_from_slice(&data[..data_len]); - } else { - let mask: i64 = (1 << basek) - 1; - let steps: usize = size.min(log_max.div_ceil(basek)); - (size - steps..size) - .rev() - .enumerate() - .for_each(|(i, i_rev)| { - let shift: usize = i * basek; - izip!(a.at_mut(res_col, i_rev).iter_mut(), data.iter()).for_each(|(y, x)| *y = (x >> shift) & mask); - }) - } - - // Case where self.prec % self.k != 0. - if k_rem != basek { - let steps: usize = size.min(log_max.div_ceil(basek)); - (size - steps..size).rev().for_each(|i| { - a.at_mut(res_col, i)[..data_len] - .iter_mut() - .for_each(|x| *x <<= k_rem); - }) - } - } -} - -unsafe impl<B: Backend> VecZnxEncodeCoeffsi64Impl<B> for B -where - B: CPUAVX, -{ - fn encode_coeff_i64_impl<R>( - _module: &Module<B>, - basek: usize, - res: &mut R, - res_col: usize, - k: usize, - i: usize, - data: i64, - log_max: usize, - ) where - R: VecZnxToMut, - { - let size: usize = k.div_ceil(basek); - - #[cfg(debug_assertions)] - { - let a: VecZnx<&mut [u8]> = res.to_mut(); - assert!(i < a.n()); - assert!( - size <= a.size(), - "invalid argument k: k.div_ceil(basek)={} > a.size()={}", - size, - a.size() - ); - assert!(res_col < a.cols()); - } - - let k_rem: usize = basek - (k % basek); - let mut a: VecZnx<&mut [u8]> = res.to_mut(); - (0..a.size()).for_each(|j| a.at_mut(res_col, j)[i] = 0); - - // If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy - // values on the last limb. - // Else we decompose values base2k. - if log_max + k_rem < 63 || k_rem == basek { - a.at_mut(res_col, size - 1)[i] = data; - } else { - let mask: i64 = (1 << basek) - 1; - let steps: usize = size.min(log_max.div_ceil(basek)); - (size - steps..size) - .rev() - .enumerate() - .for_each(|(j, j_rev)| { - a.at_mut(res_col, j_rev)[i] = (data >> (j * basek)) & mask; - }) - } - - // Case where prec % k != 0. - if k_rem != basek { - let steps: usize = size.min(log_max.div_ceil(basek)); - (size - steps..size).rev().for_each(|j| { - a.at_mut(res_col, j)[i] <<= k_rem; - }) - } - } -} - -unsafe impl<B: Backend> VecZnxDecodeVeci64Impl<B> for B -where - B: CPUAVX, -{ - fn decode_vec_i64_impl<R>(_module: &Module<B>, basek: usize, res: &R, res_col: usize, k: usize, data: &mut [i64]) - where - R: VecZnxToRef, - { - let size: usize = k.div_ceil(basek); - #[cfg(debug_assertions)] - { - let a: VecZnx<&[u8]> = res.to_ref(); - assert!( - data.len() >= a.n(), - "invalid data: data.len()={} < a.n()={}", - data.len(), - a.n() - ); - assert!(res_col < a.cols()); - } - - let a: VecZnx<&[u8]> = res.to_ref(); - data.copy_from_slice(a.at(res_col, 0)); - let rem: usize = basek - (k % basek); - if k < basek { - data.iter_mut().for_each(|x| *x >>= rem); - } else { - (1..size).for_each(|i| { - if i == size - 1 && rem != basek { - let k_rem: usize = basek - rem; - izip!(a.at(res_col, i).iter(), data.iter_mut()).for_each(|(x, y)| { - *y = (*y << k_rem) + (x >> rem); - }); - } else { - izip!(a.at(res_col, i).iter(), data.iter_mut()).for_each(|(x, y)| { - *y = (*y << basek) + x; - }); - } - }) - } - } -} - -unsafe impl<B: Backend> VecZnxDecodeCoeffsi64Impl<B> for B -where - B: CPUAVX, -{ - fn decode_coeff_i64_impl<R>(_module: &Module<B>, basek: usize, res: &R, res_col: usize, k: usize, i: usize) -> i64 - where - R: VecZnxToRef, - { - #[cfg(debug_assertions)] - { - let a: VecZnx<&[u8]> = res.to_ref(); - assert!(i < a.n()); - assert!(res_col < a.cols()) - } - - let a: VecZnx<&[u8]> = res.to_ref(); - let size: usize = k.div_ceil(basek); - let mut res: i64 = 0; - let rem: usize = basek - (k % basek); - (0..size).for_each(|j| { - let x: i64 = a.at(res_col, j)[i]; - if j == size - 1 && rem != basek { - let k_rem: usize = basek - rem; - res = (res << k_rem) + (x >> rem); - } else { - res = (res << basek) + x; - } - }); - res - } -} - -unsafe impl<B: Backend> VecZnxDecodeVecFloatImpl<B> for B -where - B: CPUAVX, -{ - fn decode_vec_float_impl<R>(_module: &Module<B>, basek: usize, res: &R, res_col: usize, data: &mut [Float]) - where - R: VecZnxToRef, - { - #[cfg(debug_assertions)] - { - let a: VecZnx<&[u8]> = res.to_ref(); - assert!( - data.len() >= a.n(), - "invalid data: data.len()={} < a.n()={}", - data.len(), - a.n() - ); - assert!(res_col < a.cols()); - } - - let a: VecZnx<&[u8]> = res.to_ref(); - let size: usize = a.size(); - let prec: u32 = (basek * size) as u32; - - // 2^{basek} - let base = Float::with_val(prec, (1 << basek) as f64); - - // y[i] = sum x[j][i] * 2^{-basek*j} - (0..size).for_each(|i| { - if i == 0 { - izip!(a.at(res_col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| { - y.assign(*x); - *y /= &base; - }); - } else { - izip!(a.at(res_col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| { - *y += Float::with_val(prec, *x); - *y /= &base; - }); - } - }); - } -}
@@ -10,12 +10,14 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, SvpPPol, VecZnx},
}; use itertools::izip; -use crate::{ - GLWEOps, Infos, LookUpTableRotationDirection, TakeGLWECt, - blind_rotation::{key::BlindRotationKeyCGGIExec, lut::LookUpTable}, - dist::Distribution, - layouts::{GLWECiphertext, GLWECiphertextToMut, LWECiphertext, LWECiphertextToRef}, +use core::{ + Distribution, GLWEOperations, TakeGLWECt, + layouts::{GLWECiphertext, GLWECiphertextToMut, Infos, LWECiphertext, LWECiphertextToRef}, trait_families::GLWEExternalProductFamily, +}; + +use crate::tfhe::blind_rotation::{ + BlincRotationExecute, BlindRotationKeyPrepared, CGGI, LookUpTable, LookUpTableRotationDirection, }; pub trait CCGIBlindRotationFamily<B: Backend> = VecZnxBigAllocBytes@@ -85,50 +87,47 @@ + GLWECiphertext::external_product_scratch_space(module, n, basek, k_res, k_res, k_brk, 1, rank)
} } -pub fn cggi_blind_rotate<DataRes, DataIn, DataBrk, B: Backend>( - module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - lwe: &LWECiphertext<DataIn>, - lut: &LookUpTable, - brk: &BlindRotationKeyCGGIExec<DataBrk, B>, - scratch: &mut Scratch<B>, -) where - DataRes: DataMut, - DataIn: DataRef, - DataBrk: DataRef, +impl<D: DataRef, B: Backend> BlincRotationExecute<B> for BlindRotationKeyPrepared<D, CGGI, B> +where Module<B>: CCGIBlindRotationFamily<B>, - Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx + ScratchAvailable + TakeVecZnxSlice, + Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + TakeVecZnx + ScratchAvailable, { - match brk.dist { - Distribution::BinaryBlock(_) | Distribution::BinaryFixed(_) | Distribution::BinaryProb(_) | Distribution::ZERO => { - if lut.extension_factor() > 1 { - cggi_blind_rotate_block_binary_extended(module, res, lwe, lut, brk, scratch); - } else if brk.block_size() > 1 { - cggi_blind_rotate_block_binary(module, res, lwe, lut, brk, scratch); - } else { - cggi_blind_rotate_binary_standard(module, res, lwe, lut, brk, scratch); + fn execute<DR: DataMut, DI: DataRef>( + &self, + module: &Module<B>, + res: &mut GLWECiphertext<DR>, + lwe: &LWECiphertext<DI>, + lut: &LookUpTable, + scratch: &mut Scratch<B>, + ) { + match self.dist { + Distribution::BinaryBlock(_) | Distribution::BinaryFixed(_) | Distribution::BinaryProb(_) | Distribution::ZERO => { + if lut.extension_factor() > 1 { + execute_block_binary_extended(module, res, lwe, lut, self, scratch) + } else if self.block_size() > 1 { + execute_block_binary(module, res, lwe, lut, self, scratch); + } else { + execute_standard(module, res, lwe, lut, self, scratch); + } } + _ => panic!("invalid CGGI distribution"), } - // TODO: ternary distribution ? - _ => panic!( - "invalid BlindRotationKeyCGGI distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" - ), } } -pub(crate) fn cggi_blind_rotate_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>( +fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, res: &mut GLWECiphertext<DataRes>, lwe: &LWECiphertext<DataIn>, lut: &LookUpTable, - brk: &BlindRotationKeyCGGIExec<DataBrk, B>, + brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>, ) where DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, Module<B>: CCGIBlindRotationFamily<B>, - Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice, + Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx, { let n_glwe: usize = brk.n(); let extension_factor: usize = lut.extension_factor();@@ -196,7 +195,7 @@ let ai_lo: usize = ai_pos & (extension_factor - 1);
// vmp_res = DFT(acc) * BRK[i] (0..extension_factor).for_each(|i| { - module.vmp_apply(&mut vmp_res[i], &acc_dft[i], &skii.data, scratch5); + module.vmp_apply(&mut vmp_res[i], &acc_dft[i], skii.data(), scratch5); }); // Trivial case: no rotation between polynomials, we can directly multiply with (X^{-ai} - 1)@@ -261,19 +260,19 @@ module.vec_znx_copy(&mut res.data, i, &acc[0], i);
}); } -pub(crate) fn cggi_blind_rotate_block_binary<DataRes, DataIn, DataBrk, B: Backend>( +fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, res: &mut GLWECiphertext<DataRes>, lwe: &LWECiphertext<DataIn>, lut: &LookUpTable, - brk: &BlindRotationKeyCGGIExec<DataBrk, B>, + brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>, ) where DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, Module<B>: CCGIBlindRotationFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnxBig<B>, + Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx, { let n_glwe: usize = brk.n(); let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space@@ -331,7 +330,7 @@ izip!(ai.iter(), ski.iter()).for_each(|(aii, skii)| {
let ai_pos: usize = ((aii + two_n as i64) & (two_n - 1) as i64) as usize; // vmp_res = DFT(acc) * BRK[i] - module.vmp_apply(&mut vmp_res, &acc_dft, &skii.data, scratch4); + module.vmp_apply(&mut vmp_res, &acc_dft, skii.data(), scratch4); // DFT(X^ai -1) * (DFT(acc) * BRK[i]) (0..cols).for_each(|i| {@@ -353,19 +352,19 @@ }
}); } -pub(crate) fn cggi_blind_rotate_binary_standard<DataRes, DataIn, DataBrk, B: Backend>( +fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, res: &mut GLWECiphertext<DataRes>, lwe: &LWECiphertext<DataIn>, lut: &LookUpTable, - brk: &BlindRotationKeyCGGIExec<DataBrk, B>, + brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>, ) where DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, Module<B>: CCGIBlindRotationFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx + ScratchAvailable, + Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx, { #[cfg(debug_assertions)] {@@ -445,7 +444,7 @@ let basek: usize = lwe.basek();
let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1; - res.copy_from_slice(&lwe.data.at(0, 0)); + res.copy_from_slice(&lwe.data().at(0, 0)); match rot_dir { LookUpTableRotationDirection::Left => {@@ -465,11 +464,11 @@ let size: usize = log2n.div_ceil(basek);
(1..size).for_each(|i| { if i == size - 1 && rem != basek { let k_rem: usize = basek - rem; - izip!(lwe.data.at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| { + izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| { *y = (*y << k_rem) + (x >> rem); }); } else { - izip!(lwe.data.at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| { + izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| { *y = (*y << basek) + x; }); }
@@ -1,362 +0,0 @@
-use backend::hal::{ - api::{ - FillUniform, Reset, ScratchAvailable, SvpPPolAlloc, SvpPrepare, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, - VmpPMatAlloc, VmpPMatPrepare, ZnxInfos, ZnxView, ZnxViewMut, - }, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToRef, Scratch, SvpPPol, WriterTo}, -}; -use sampling::source::Source; - -use crate::{ - Distribution, Infos, - layouts::{ - GGSWCiphertext, LWESecret, - prepared::{GGSWCiphertextExec, GLWESecretExec}, - }, -}; -use std::fmt; - -use crate::trait_families::GGSWEncryptSkFamily; - -#[derive(Clone)] -pub struct BlindRotationKeyCGGI<D: Data> { - pub(crate) keys: Vec<GGSWCiphertext<D>>, - pub(crate) dist: Distribution, -} - -impl<D: DataRef> fmt::Debug for BlindRotationKeyCGGI<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: Data> PartialEq for BlindRotationKeyCGGI<D> { - fn eq(&self, other: &Self) -> bool { - if self.keys.len() != other.keys.len() { - return false; - } - for (a, b) in self.keys.iter().zip(other.keys.iter()) { - if a != b { - return false; - } - } - self.dist == other.dist - } -} - -impl<D: Data> Eq for BlindRotationKeyCGGI<D> {} - -impl<D: DataRef> fmt::Display for BlindRotationKeyCGGI<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, key) in self.keys.iter().enumerate() { - write!(f, "key[{}]: {}", i, key)?; - } - writeln!(f, "{:?}", self.dist) - } -} - -impl<D: DataMut> Reset for BlindRotationKeyCGGI<D> { - fn reset(&mut self) { - self.keys.iter_mut().for_each(|key| key.reset()); - self.dist = Distribution::NONE; - } -} - -impl<D: DataMut> FillUniform for BlindRotationKeyCGGI<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key| key.fill_uniform(source)); - } -} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for BlindRotationKeyCGGI<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - let len: usize = reader.read_u64::<LittleEndian>()? as usize; - if self.keys.len() != len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("self.keys.len()={} != read len={}", self.keys.len(), len), - )); - } - for key in &mut self.keys { - key.read_from(reader)?; - } - Ok(()) - } -} - -impl<D: DataRef> WriterTo for BlindRotationKeyCGGI<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - match self.dist.write_to(writer) { - Ok(()) => {} - Err(e) => return Err(e), - } - writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} - -impl BlindRotationKeyCGGI<Vec<u8>> { - pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { - let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe); - (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank))); - Self { - keys: data, - dist: Distribution::NONE, - } - } - - pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GGSWEncryptSkFamily<B>, - { - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl<D: DataRef> BlindRotationKeyCGGI<D> { - #[allow(dead_code)] - pub(crate) fn n(&self) -> usize { - self.keys[0].n() - } - - #[allow(dead_code)] - pub(crate) fn rows(&self) -> usize { - self.keys[0].rows() - } - - #[allow(dead_code)] - pub(crate) fn k(&self) -> usize { - self.keys[0].k() - } - - #[allow(dead_code)] - pub(crate) fn size(&self) -> usize { - self.keys[0].size() - } - - #[allow(dead_code)] - pub(crate) fn rank(&self) -> usize { - self.keys[0].rank() - } - - pub(crate) fn basek(&self) -> usize { - self.keys[0].basek() - } - - #[allow(dead_code)] - pub(crate) fn block_size(&self) -> usize { - match self.dist { - Distribution::BinaryBlock(value) => value, - _ => 1, - } - } -} - -impl<D: DataMut> BlindRotationKeyCGGI<D> { - pub fn generate_from_sk<DataSkGLWE, DataSkLWE, B: Backend>( - &mut self, - module: &Module<B>, - sk_glwe: &GLWESecretExec<DataSkGLWE, B>, - sk_lwe: &LWESecret<DataSkLWE>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DataSkGLWE: DataRef, - DataSkLWE: DataRef, - Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.keys.len(), sk_lwe.n()); - assert!(sk_glwe.n() <= module.n()); - assert_eq!(sk_glwe.rank(), self.keys[0].rank()); - match sk_lwe.dist { - Distribution::BinaryBlock(_) - | Distribution::BinaryFixed(_) - | Distribution::BinaryProb(_) - | Distribution::ZERO => {} - _ => panic!( - "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" - ), - } - } - - self.dist = sk_lwe.dist; - - let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1); - let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data.to_ref(); - - self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| { - pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i]; - ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, sigma, scratch); - }); - } -} - -#[derive(PartialEq, Eq)] -pub struct BlindRotationKeyCGGIExec<D: Data, B: Backend> { - pub(crate) data: Vec<GGSWCiphertextExec<D, B>>, - pub(crate) dist: Distribution, - pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>, -} - -impl<D: Data, B: Backend> BlindRotationKeyCGGIExec<D, B> { - #[allow(dead_code)] - pub(crate) fn n(&self) -> usize { - self.data[0].n() - } - - #[allow(dead_code)] - pub(crate) fn rows(&self) -> usize { - self.data[0].rows() - } - - #[allow(dead_code)] - pub(crate) fn k(&self) -> usize { - self.data[0].k() - } - - #[allow(dead_code)] - pub(crate) fn size(&self) -> usize { - self.data[0].size() - } - - #[allow(dead_code)] - pub(crate) fn rank(&self) -> usize { - self.data[0].rank() - } - - pub(crate) fn basek(&self) -> usize { - self.data[0].basek() - } - - pub(crate) fn block_size(&self) -> usize { - match self.dist { - Distribution::BinaryBlock(value) => value, - _ => 1, - } - } -} - -pub trait BlindRotationKeyCGGIExecLayoutFamily<B: Backend> = SvpPPolAlloc<B> + SvpPrepare<B>; - -impl<B: Backend> BlindRotationKeyCGGIExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self - where - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut data: Vec<GGSWCiphertextExec<Vec<u8>, B>> = Vec::with_capacity(n_lwe); - (0..n_lwe).for_each(|_| { - data.push(GGSWCiphertextExec::alloc( - module, n_glwe, basek, k, rows, 1, rank, - )) - }); - Self { - data, - dist: Distribution::NONE, - x_pow_a: None, - } - } - - pub fn from<DataOther>(module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) -> Self - where - DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut brk: BlindRotationKeyCGGIExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.keys.len(), - other.basek(), - other.k(), - other.rows(), - other.rank(), - ); - brk.prepare(module, other, scratch); - brk - } -} - -impl<D: DataMut, B: Backend> BlindRotationKeyCGGIExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.data.len(), other.keys.len()); - } - - let n: usize = other.n(); - - self.data - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(ggsw_exec, other)| { - ggsw_exec.prepare(module, other, scratch); - }); - - self.dist = other.dist; - - match other.dist { - Distribution::BinaryBlock(_) => { - let mut x_pow_a: Vec<SvpPPol<Vec<u8>, B>> = Vec::with_capacity(n << 1); - let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - (0..n << 1).for_each(|i| { - let mut res: SvpPPol<Vec<u8>, B> = module.svp_ppol_alloc(n, 1); - set_xai_plus_y(module, i, 0, &mut res, &mut buf); - x_pow_a.push(res); - }); - self.x_pow_a = Some(x_pow_a); - } - _ => {} - } - } -} - -pub fn set_xai_plus_y<A, C, B: Backend>(module: &Module<B>, ai: usize, y: i64, res: &mut SvpPPol<A, B>, buf: &mut ScalarZnx<C>) -where - A: DataMut, - C: DataMut, - Module<B>: SvpPrepare<B>, -{ - let n: usize = res.n(); - - { - let raw: &mut [i64] = buf.at_mut(0, 0); - if ai < n { - raw[ai] = 1; - } else { - raw[(ai - n) & (n - 1)] = -1; - } - raw[0] += y; - } - - module.svp_prepare(res, 0, buf, 0); - - { - let raw: &mut [i64] = buf.at_mut(0, 0); - - if ai < n { - raw[ai] = 0; - } else { - raw[(ai - n) & (n - 1)] = 0; - } - raw[0] = 0; - } -}
@@ -1,217 +0,0 @@
-use backend::hal::{ - api::{FillUniform, Reset, ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, ZnxView, ZnxViewMut}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToRef, Scratch, WriterTo}, -}; -use sampling::source::Source; - -use crate::{ - Distribution, Infos, - layouts::{LWESecret, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, -}; -use std::fmt; - -use crate::trait_families::GGSWEncryptSkFamily; - -#[derive(Clone)] -pub struct BlindRotationKeyCGGICompressed<D: Data> { - pub(crate) keys: Vec<GGSWCiphertextCompressed<D>>, - pub(crate) dist: Distribution, -} - -impl<D: DataRef> fmt::Debug for BlindRotationKeyCGGICompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) - } -} - -impl<D: Data> PartialEq for BlindRotationKeyCGGICompressed<D> { - fn eq(&self, other: &Self) -> bool { - if self.keys.len() != other.keys.len() { - return false; - } - for (a, b) in self.keys.iter().zip(other.keys.iter()) { - if a != b { - return false; - } - } - self.dist == other.dist - } -} - -impl<D: Data> Eq for BlindRotationKeyCGGICompressed<D> {} - -impl<D: DataRef> fmt::Display for BlindRotationKeyCGGICompressed<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, key) in self.keys.iter().enumerate() { - write!(f, "key[{}]: {}", i, key)?; - } - writeln!(f, "{:?}", self.dist) - } -} - -impl<D: DataMut> Reset for BlindRotationKeyCGGICompressed<D> { - fn reset(&mut self) { - self.keys.iter_mut().for_each(|key| key.reset()); - self.dist = Distribution::NONE; - } -} - -impl<D: DataMut> FillUniform for BlindRotationKeyCGGICompressed<D> { - fn fill_uniform(&mut self, source: &mut sampling::source::Source) { - self.keys - .iter_mut() - .for_each(|key| key.fill_uniform(source)); - } -} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for BlindRotationKeyCGGICompressed<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - let len: usize = reader.read_u64::<LittleEndian>()? as usize; - if self.keys.len() != len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("self.keys.len()={} != read len={}", self.keys.len(), len), - )); - } - for key in &mut self.keys { - key.read_from(reader)?; - } - Ok(()) - } -} - -impl<D: DataRef> WriterTo for BlindRotationKeyCGGICompressed<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - match self.dist.write_to(writer) { - Ok(()) => {} - Err(e) => return Err(e), - } - writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} - -impl BlindRotationKeyCGGICompressed<Vec<u8>> { - pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { - let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(n_lwe); - (0..n_lwe).for_each(|_| { - data.push(GGSWCiphertextCompressed::alloc( - n_gglwe, basek, k, rows, 1, rank, - )) - }); - Self { - keys: data, - dist: Distribution::NONE, - } - } - - pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GGSWEncryptSkFamily<B>, - { - GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl<D: DataRef> BlindRotationKeyCGGICompressed<D> { - #[allow(dead_code)] - pub(crate) fn n(&self) -> usize { - self.keys[0].n() - } - - #[allow(dead_code)] - pub(crate) fn rows(&self) -> usize { - self.keys[0].rows() - } - - #[allow(dead_code)] - pub(crate) fn k(&self) -> usize { - self.keys[0].k() - } - - #[allow(dead_code)] - pub(crate) fn size(&self) -> usize { - self.keys[0].size() - } - - #[allow(dead_code)] - pub(crate) fn rank(&self) -> usize { - self.keys[0].rank() - } - - #[allow(dead_code)] - pub(crate) fn basek(&self) -> usize { - self.keys[0].basek() - } - - #[allow(dead_code)] - pub(crate) fn block_size(&self) -> usize { - match self.dist { - Distribution::BinaryBlock(value) => value, - _ => 1, - } - } -} - -impl<D: DataMut> BlindRotationKeyCGGICompressed<D> { - pub fn generate_from_sk<DataSkGLWE, DataSkLWE, B: Backend>( - &mut self, - module: &Module<B>, - sk_glwe: &GLWESecretExec<DataSkGLWE, B>, - sk_lwe: &LWESecret<DataSkLWE>, - seed_xa: [u8; 32], - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DataSkGLWE: DataRef, - DataSkLWE: DataRef, - Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.keys.len(), sk_lwe.n()); - assert!(sk_glwe.n() <= module.n()); - assert_eq!(sk_glwe.rank(), self.keys[0].rank()); - match sk_lwe.dist { - Distribution::BinaryBlock(_) - | Distribution::BinaryFixed(_) - | Distribution::BinaryProb(_) - | Distribution::ZERO => {} - _ => panic!( - "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" - ), - } - } - - self.dist = sk_lwe.dist; - - let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1); - let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data.to_ref(); - - let mut source_xa: Source = Source::new(seed_xa); - - self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| { - pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i]; - ggsw.encrypt_sk( - module, - &pt, - sk_glwe, - source_xa.new_seed(), - source_xe, - sigma, - scratch, - ); - }); - } -}
@@ -1,12 +0,0 @@
-mod cggi; -mod key; -mod key_compressed; -mod lut; - -pub use cggi::*; -pub use key::*; -pub use key_compressed::*; -pub use lut::*; - -#[cfg(test)] -mod tests;
@@ -3,8 +3,8 @@ hal::{api::ModuleNew, layouts::Module},
implementation::cpu_spqlios::FFT64, }; -use crate::blind_rotation::tests::{ - generic_cggi::blind_rotatio_test, +use crate::tfhe::blind_rotation::tests::{ + generic_blind_rotation::test_blind_rotation, generic_lut::{test_lut_extended, test_lut_standard}, };@@ -23,17 +23,17 @@
#[test] fn standard() { let module: Module<FFT64> = Module::<FFT64>::new(512); - blind_rotatio_test(&module, 224, 1, 1); + test_blind_rotation(&module, 224, 1, 1); } #[test] fn block_binary() { let module: Module<FFT64> = Module::<FFT64>::new(512); - blind_rotatio_test(&module, 224, 7, 1); + test_blind_rotation(&module, 224, 7, 1); } #[test] fn block_binary_extended() { let module: Module<FFT64> = Module::<FFT64>::new(512); - blind_rotatio_test(&module, 224, 7, 2); + test_blind_rotation(&module, 224, 7, 2); }
@@ -1,163 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxEncodeCoeffsi64, VecZnxFillUniform, - VecZnxRotateInplace, VecZnxSub, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, - }, - layouts::{Backend, Module, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, - TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, Infos, - LookUpTable, cggi_blind_rotate, cggi_blind_rotate_scratch_space, - layouts::{ - GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWECiphertextToRef, LWEPlaintext, LWESecret, - prepared::GLWESecretExec, - }, - mod_switch_2n, -}; - -use crate::trait_families::{GLWEDecryptFamily, GLWESecretExecModuleFamily}; - -pub(crate) trait CGGITestModuleFamily<B: Backend> = CCGIBlindRotationFamily<B> - + GLWESecretExecModuleFamily<B> - + GLWEDecryptFamily<B> - + BlindRotationKeyCGGIExecLayoutFamily<B> - + VecZnxFillUniform - + VecZnxAddNormal - + VecZnxAddScalarInplace - + VecZnxEncodeCoeffsi64 - + VecZnxRotateInplace - + VecZnxSwithcDegree - + VecZnxSub - + VmpPMatAlloc<B> - + VmpPMatPrepare<B>; -pub(crate) trait CGGITestScratchFamily<B: Backend> = VecZnxDftAllocBytesImpl<B> - + VecZnxBigAllocBytesImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeVecZnxDftSliceImpl<B> - + ScratchAvailableImpl<B> - + TakeVecZnxImpl<B> - + TakeVecZnxSliceImpl<B>; - -pub(crate) fn blind_rotatio_test<B: Backend>(module: &Module<B>, n_lwe: usize, block_size: usize, extension_factor: usize) -where - Module<B>: CGGITestModuleFamily<B>, - B: CGGITestScratchFamily<B>, -{ - let n: usize = module.n(); - let basek: usize = 19; - let k_lwe: usize = 24; - let k_brk: usize = 3 * basek; - let rows_brk: usize = 2; // Ensures first limb is noise-free. - let k_lut: usize = 1 * basek; - let k_res: usize = 2 * basek; - let rank: usize = 1; - - let message_modulus: usize = 1 << 4; - - let mut source_xs: Source = Source::new([2u8; 32]); - let mut source_xe: Source = Source::new([2u8; 32]); - let mut source_xa: Source = Source::new([1u8; 32]); - - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); - - let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe); - sk_lwe.fill_binary_block(block_size, &mut source_xs); - - let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKeyCGGI::generate_from_sk_scratch_space( - module, n, basek, k_brk, rank, - )); - - let mut scratch_br: ScratchOwned<B> = ScratchOwned::<B>::alloc(cggi_blind_rotate_scratch_space( - module, - n, - block_size, - extension_factor, - basek, - k_res, - k_brk, - rows_brk, - rank, - )); - - let mut brk: BlindRotationKeyCGGI<Vec<u8>> = BlindRotationKeyCGGI::alloc(n, n_lwe, basek, k_brk, rows_brk, rank); - - brk.generate_from_sk( - module, - &sk_glwe_dft, - &sk_lwe, - &mut source_xa, - &mut source_xe, - 3.2, - scratch.borrow(), - ); - - let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe); - - let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe); - - let x: i64 = 2; - let bits: usize = 8; - - module.encode_coeff_i64(basek, &mut pt_lwe.data, 0, bits, 0, x, bits); - - lwe.encrypt_sk( - module, - &pt_lwe, - &sk_lwe, - &mut source_xa, - &mut source_xe, - 3.2, - ); - - let mut f: Vec<i64> = vec![0i64; message_modulus]; - f.iter_mut() - .enumerate() - .for_each(|(i, x)| *x = 2 * (i as i64) + 1); - - let mut lut: LookUpTable = LookUpTable::alloc(n, basek, k_lut, extension_factor); - lut.set(module, &f, message_modulus); - - let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_res, rank); - - let brk_exec: BlindRotationKeyCGGIExec<Vec<u8>, B> = BlindRotationKeyCGGIExec::from(module, &brk, scratch_br.borrow()); - - cggi_blind_rotate(module, &mut res, &lwe, &lut, &brk_exec, scratch_br.borrow()); - - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_res); - - res.decrypt(module, &mut pt_have, &sk_glwe_dft, scratch.borrow()); - - let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space - - mod_switch_2n( - 2 * lut.domain_size(), - &mut lwe_2n, - &lwe.to_ref(), - lut.rotation_direction(), - ); - - let pt_want: i64 = (lwe_2n[0] - + lwe_2n[1..] - .iter() - .zip(sk_lwe.data.at(0, 0)) - .map(|(x, y)| x * y) - .sum::<i64>()) - & (2 * lut.domain_size() - 1) as i64; - - lut.rotate(module, pt_want); - - // First limb should be exactly equal (test are parameterized such that the noise does not reach - // the first limb) - assert_eq!(pt_have.data.at(0, 0), lut.data[0].at(0, 0)); -}
@@ -1,23 +1,16 @@
use std::vec; use backend::hal::{ - api::{ - VecZnxCopy, VecZnxDecodeVeci64, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSwithcDegree, - }, + api::{VecZnxCopy, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSwithcDegree}, layouts::{Backend, Module}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::{DivRound, LookUpTable}; +use crate::tfhe::blind_rotation::{DivRound, LookUpTable}; -pub(crate) fn test_lut_standard<B: Backend>(module: &Module<B>) +pub fn test_lut_standard<B: Backend>(module: &Module<B>) where - Module<B>: VecZnxRotateInplace - + VecZnxNormalizeInplace<B> - + VecZnxNormalizeTmpBytes - + VecZnxSwithcDegree - + VecZnxCopy - + VecZnxDecodeVeci64, + Module<B>: VecZnxRotateInplace + VecZnxNormalizeInplace<B> + VecZnxNormalizeTmpBytes + VecZnxSwithcDegree + VecZnxCopy, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let n: usize = module.n();@@ -42,7 +35,7 @@
let step: usize = lut.domain_size().div_round(message_modulus); let mut lut_dec: Vec<i64> = vec![0i64; module.n()]; - module.decode_vec_i64(basek, &lut.data[0], 0, log_scale, &mut lut_dec); + lut.data[0].decode_vec_i64(basek, 0, log_scale, &mut lut_dec); (0..lut.domain_size()).step_by(step).for_each(|i| { (0..step).for_each(|_| {@@ -51,14 +44,9 @@ });
}); } -pub(crate) fn test_lut_extended<B: Backend>(module: &Module<B>) +pub fn test_lut_extended<B: Backend>(module: &Module<B>) where - Module<B>: VecZnxRotateInplace - + VecZnxNormalizeInplace<B> - + VecZnxNormalizeTmpBytes - + VecZnxSwithcDegree - + VecZnxCopy - + VecZnxDecodeVeci64, + Module<B>: VecZnxRotateInplace + VecZnxNormalizeInplace<B> + VecZnxNormalizeTmpBytes + VecZnxSwithcDegree + VecZnxCopy, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let n: usize = module.n();@@ -85,7 +73,7 @@
let mut lut_dec: Vec<i64> = vec![0i64; module.n()]; (0..extension_factor).for_each(|ext| { - module.decode_vec_i64(basek, &lut.data[ext], 0, log_scale, &mut lut_dec); + lut.data[ext].decode_vec_i64(basek, 0, log_scale, &mut lut_dec); (0..module.n()).step_by(step).for_each(|i| { (0..step).for_each(|_| { assert_eq!(f[i / step] % message_modulus as i64, lut_dec[i]);
@@ -1,15 +0,0 @@
-use backend::hal::tests::serialization::test_reader_writer_interface; - -use crate::{BlindRotationKeyCGGI, BlindRotationKeyCGGICompressed}; - -#[test] -fn test_cggi_blind_rotation_key_serialization() { - let original: BlindRotationKeyCGGI<Vec<u8>> = BlindRotationKeyCGGI::alloc(256, 64, 12, 54, 2, 2); - test_reader_writer_interface(original); -} - -#[test] -fn test_cggi_blind_rotation_key_compressed_serialization() { - let original: BlindRotationKeyCGGICompressed<Vec<u8>> = BlindRotationKeyCGGICompressed::alloc(256, 64, 12, 54, 2, 2); - test_reader_writer_interface(original); -}
@@ -1,396 +0,0 @@
-use backend::hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, - }, - layouts::{Backend, Module, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, - TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, - }, -}; -use sampling::source::Source; - -use crate::{ - AutomorphismKey, AutomorphismKeyCompressed, AutomorphismKeyEncryptSkFamily, AutomorphismKeyExec, GGLWEExecLayoutFamily, - GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPlaintext, GLWESecret, GLWESecretExec, Infos, - noise::log2_std_noise_gglwe_product, -}; - -pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = AutomorphismKeyEncryptSkFamily<B> - + GLWEKeyswitchFamily<B> - + VecZnxAutomorphism - + GGLWEExecLayoutFamily<B> - + VecZnxSwithcDegree - + VecZnxAddScalarInplace - + VecZnxAutomorphism - + VecZnxAutomorphismInplace - + GLWEDecryptFamily<B> - + VecZnxSubScalarInplace - + VecZnxStd - + VecZnxCopy; -pub(crate) trait AutomorphismTestScratchFamily<B: Backend> = ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxDftImpl<B> - + TakeVecZnxImpl<B> - + TakeSvpPPolImpl<B> - + TakeVecZnxBigImpl<B>; - -pub(crate) fn test_automorphisk_key_encrypt_sk<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = TakeScalarZnx; - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - let p = -5; - - atk.encrypt_sk( - module, - p, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); - (0..atk.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - let sk_out_exec = GLWESecretExec::from(module, &sk_out); - - atk.key - .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); -} - -pub(crate) fn test_automorphisk_key_encrypt_sk_compressed<B: Backend>( - module: &Module<B>, - basek: usize, - k_ksk: usize, - digits: usize, - rank: usize, - sigma: f64, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = TakeScalarZnx; - let rows: usize = (k_ksk - digits * basek) / (digits * basek); - - let mut atk_compressed: AutomorphismKeyCompressed<Vec<u8>> = - AutomorphismKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space( - module, n, basek, k_ksk, rank, - )); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - let p = -5; - - let seed_xa: [u8; 32] = [1u8; 32]; - - atk_compressed.encrypt_sk( - module, - p, - &sk, - seed_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut sk_out: GLWESecret<Vec<u8>> = sk.clone(); - (0..atk_compressed.rank()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), - &mut sk_out.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - let sk_out_exec = GLWESecretExec::from(module, &sk_out); - - let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); - atk.decompress(module, &atk_compressed); - - atk.key - .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); -} - -pub(crate) fn test_gglwe_automorphism<B: Backend>( - module: &Module<B>, - p0: i64, - p1: i64, - basek: usize, - digits: usize, - k_in: usize, - k_out: usize, - k_apply: usize, - sigma: f64, - rank: usize, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = TakeScalarZnx; - let digits_in: usize = 1; - - let rows_in: usize = k_in / (basek * digits); - let rows_apply: usize = k_in.div_ceil(basek * digits); - - let mut auto_key_in: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_out: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) - | AutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_in, k_apply, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(TakeScalarZnx, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - // gglwe_{s1}(s0) = s0 -> s1 - auto_key_in.encrypt_sk( - module, - p0, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - auto_key_apply.encrypt_sk( - module, - p1, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key_out.automorphism(module, &auto_key_in, &auto_key_apply_exec, scratch.borrow()); - - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(TakeScalarZnx, basek, k_out); - - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(TakeScalarZnx, rank); - sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk - (0..rank).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p0 * p1), - &mut sk_auto.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); - - (0..auto_key_out.rank_in()).for_each(|col_i| { - (0..auto_key_out.rows()).for_each(|row_i| { - auto_key_out - .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); - - module.vec_znx_sub_scalar_inplace( - &mut pt.data, - 0, - (digits_in - 1) + row_i * digits_in, - &sk.data, - col_i, - ); - - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); - let noise_want: f64 = log2_std_noise_gglwe_product( - TakeScalarZnx as f64, - basek * digits, - 0.5, - 0.5, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_out, - k_apply, - ); - - assert!( - noise_have < noise_want + 0.5, - "{} {}", - noise_have, - noise_want - ); - }); - }); -} - -pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>( - module: &Module<B>, - p0: i64, - p1: i64, - basek: usize, - digits: usize, - k_in: usize, - k_apply: usize, - sigma: f64, - rank: usize, -) where - Module<B>: AutomorphismTestModuleFamily<B>, - B: AutomorphismTestScratchFamily<B>, -{ - let n: usize = TakeScalarZnx; - let digits_in: usize = 1; - - let rows_in: usize = k_in / (basek * digits); - let rows_apply: usize = k_in.div_ceil(basek * digits); - - let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank); - let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank); - - let mut source_xs: Source = Source::new([0u8; 32]); - let mut source_xe: Source = Source::new([0u8; 32]); - let mut source_xa: Source = Source::new([0u8; 32]); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank) - | AutomorphismKey::automorphism_inplace_scratch_space(module, n, basek, k_in, k_apply, digits, rank), - ); - - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(TakeScalarZnx, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - - // gglwe_{s1}(s0) = s0 -> s1 - auto_key.encrypt_sk( - module, - p0, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - // gglwe_{s2}(s1) -> s1 -> s2 - auto_key_apply.encrypt_sk( - module, - p1, - &sk, - &mut source_xa, - &mut source_xe, - sigma, - scratch.borrow(), - ); - - let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> = - AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); - - // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key.automorphism_inplace(module, &auto_key_apply_exec, scratch.borrow()); - - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(TakeScalarZnx, basek, k_in); - - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(TakeScalarZnx, rank); - sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk - - (0..rank).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p0 * p1), - &mut sk_auto.data.as_vec_znx_mut(), - i, - &sk.data.as_vec_znx(), - i, - ); - }); - - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); - - (0..auto_key.rank_in()).for_each(|col_i| { - (0..auto_key.rows()).for_each(|row_i| { - auto_key - .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow()); - module.vec_znx_sub_scalar_inplace( - &mut pt.data, - 0, - (digits_in - 1) + row_i * digits_in, - &sk.data, - col_i, - ); - - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); - let noise_want: f64 = log2_std_noise_gglwe_product( - TakeScalarZnx as f64, - basek * digits, - 0.5, - 0.5, - 0f64, - sigma * sigma, - 0f64, - rank as f64, - k_in, - k_apply, - ); - - assert!( - noise_have < noise_want + 0.5, - "{} {}", - noise_have, - noise_want - ); - }); - }); -}
@@ -1,321 +0,0 @@
-use backend::hal::{ - api::{ScratchAvailable, SvpPPolAlloc, SvpPrepare, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, ZnxView, ZnxViewMut}, - layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToRef, Scratch, SvpPPol, WriterTo}, -}; -use sampling::source::Source; - -use crate::{ - Distribution, GGSWCiphertext, GGSWCiphertextExec, GGSWEncryptSkFamily, GGSWLayoutFamily, GLWESecretExec, Infos, LWESecret, -}; - -pub struct BlindRotationKeyCGGI<D: Data> { - pub(crate) keys: Vec<GGSWCiphertext<D>>, - pub(crate) dist: Distribution, -} - -impl<D: Data> PartialEq for BlindRotationKeyCGGI<D> { - fn eq(&self, other: &Self) -> bool { - if self.keys.len() != other.keys.len() { - return false; - } - for (a, b) in self.keys.iter().zip(other.keys.iter()) { - if a != b { - return false; - } - } - self.dist == other.dist - } -} - -impl<D: Data> Eq for BlindRotationKeyCGGI<D> {} - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - -impl<D: DataMut> ReaderFrom for BlindRotationKeyCGGI<D> { - fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { - match Distribution::read_from(reader) { - Ok(dist) => self.dist = dist, - Err(e) => return Err(e), - } - let len: usize = reader.read_u64::<LittleEndian>()? as usize; - if self.keys.len() != len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("self.keys.len()={} != read len={}", self.keys.len(), len), - )); - } - for key in &mut self.keys { - key.read_from(reader)?; - } - Ok(()) - } -} - -impl<D: DataRef> WriterTo for BlindRotationKeyCGGI<D> { - fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { - match self.dist.write_to(writer) { - Ok(()) => {} - Err(e) => return Err(e), - } - writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; - for key in &self.keys { - key.write_to(writer)?; - } - Ok(()) - } -} - -impl BlindRotationKeyCGGI<Vec<u8>> { - pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { - let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe); - (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank))); - Self { - keys: data, - dist: Distribution::NONE, - } - } - - pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize - where - Module<B>: GGSWEncryptSkFamily<B>, - { - GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank) - } -} - -impl<D: DataRef> BlindRotationKeyCGGI<D> { - #[allow(dead_code)] - pub(crate) fn n(&self) -> usize { - self.keys[0].n() - } - - #[allow(dead_code)] - pub(crate) fn rows(&self) -> usize { - self.keys[0].rows() - } - - #[allow(dead_code)] - pub(crate) fn k(&self) -> usize { - self.keys[0].k() - } - - #[allow(dead_code)] - pub(crate) fn size(&self) -> usize { - self.keys[0].size() - } - - #[allow(dead_code)] - pub(crate) fn rank(&self) -> usize { - self.keys[0].rank() - } - - pub(crate) fn basek(&self) -> usize { - self.keys[0].basek() - } - - #[allow(dead_code)] - pub(crate) fn block_size(&self) -> usize { - match self.dist { - Distribution::BinaryBlock(value) => value, - _ => 1, - } - } -} - -impl<D: DataMut> BlindRotationKeyCGGI<D> { - pub fn generate_from_sk<DataSkGLWE, DataSkLWE, B: Backend>( - &mut self, - module: &Module<B>, - sk_glwe: &GLWESecretExec<DataSkGLWE, B>, - sk_lwe: &LWESecret<DataSkLWE>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) where - DataSkGLWE: DataRef, - DataSkLWE: DataRef, - Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.keys.len(), sk_lwe.n()); - assert!(sk_glwe.n() <= TakeScalarZnx); - assert_eq!(sk_glwe.rank(), self.keys[0].rank()); - match sk_lwe.dist { - Distribution::BinaryBlock(_) - | Distribution::BinaryFixed(_) - | Distribution::BinaryProb(_) - | Distribution::ZERO => {} - _ => panic!( - "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" - ), - } - } - - self.dist = sk_lwe.dist; - - let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1); - let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data.to_ref(); - - self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| { - pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i]; - ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, sigma, scratch); - }); - } -} - -#[derive(PartialEq, Eq)] -pub struct BlindRotationKeyCGGIExec<D: Data, B: Backend> { - pub(crate) data: Vec<GGSWCiphertextExec<D, B>>, - pub(crate) dist: Distribution, - pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>, -} - -impl<D: Data, B: Backend> BlindRotationKeyCGGIExec<D, B> { - #[allow(dead_code)] - pub(crate) fn n(&self) -> usize { - self.data[0].n() - } - - #[allow(dead_code)] - pub(crate) fn rows(&self) -> usize { - self.data[0].rows() - } - - #[allow(dead_code)] - pub(crate) fn k(&self) -> usize { - self.data[0].k() - } - - #[allow(dead_code)] - pub(crate) fn size(&self) -> usize { - self.data[0].size() - } - - #[allow(dead_code)] - pub(crate) fn rank(&self) -> usize { - self.data[0].rank() - } - - pub(crate) fn basek(&self) -> usize { - self.data[0].basek() - } - - pub(crate) fn block_size(&self) -> usize { - match self.dist { - Distribution::BinaryBlock(value) => value, - _ => 1, - } - } -} - -pub trait BlindRotationKeyCGGIExecLayoutFamily<B: Backend> = GGSWLayoutFamily<B> + SvpPPolAlloc<B> + SvpPrepare<B>; - -impl<B: Backend> BlindRotationKeyCGGIExec<Vec<u8>, B> { - pub fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self - where - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, - { - let mut data: Vec<GGSWCiphertextExec<Vec<u8>, B>> = Vec::with_capacity(n_lwe); - (0..n_lwe).for_each(|_| { - data.push(GGSWCiphertextExec::alloc( - module, n_glwe, basek, k, rows, 1, rank, - )) - }); - Self { - data, - dist: Distribution::NONE, - x_pow_a: None, - } - } - - pub fn from<DataOther>(module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) -> Self - where - DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, - { - let mut brk: BlindRotationKeyCGGIExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.keys.len(), - other.basek(), - other.k(), - other.rows(), - other.rank(), - ); - brk.prepare(module, other, scratch); - brk - } -} - -impl<D: DataMut, B: Backend> BlindRotationKeyCGGIExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &BlindRotationKeyCGGI<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B>, - { - #[cfg(debug_assertions)] - { - assert_eq!(self.data.len(), other.keys.len()); - } - - let n: usize = other.n(); - - self.data - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(ggsw_exec, other)| { - ggsw_exec.prepare(module, other, scratch); - }); - - self.dist = other.dist; - - match other.dist { - Distribution::BinaryBlock(_) => { - let mut x_pow_a: Vec<SvpPPol<Vec<u8>, B>> = Vec::with_capacity(n << 1); - let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - (0..n << 1).for_each(|i| { - let mut res: SvpPPol<Vec<u8>, B> = module.svp_ppol_alloc(n, 1); - set_xai_plus_y(module, i, 0, &mut res, &mut buf); - x_pow_a.push(res); - }); - self.x_pow_a = Some(x_pow_a); - } - _ => {} - } - } -} - -pub fn set_xai_plus_y<A, C, B: Backend>(module: &Module<B>, ai: usize, y: i64, res: &mut SvpPPol<A, B>, buf: &mut ScalarZnx<C>) -where - A: DataMut, - C: DataMut, - Module<B>: SvpPrepare<B>, -{ - let n: usize = res.n(); - - { - let raw: &mut [i64] = buf.at_mut(0, 0); - if ai < n { - raw[ai] = 1; - } else { - raw[(ai - n) & (n - 1)] = -1; - } - raw[0] += y; - } - - module.svp_prepare(res, 0, buf, 0); - - { - let raw: &mut [i64] = buf.at_mut(0, 0); - - if ai < n { - raw[ai] = 0; - } else { - raw[(ai - n) & (n - 1)] = 0; - } - raw[0] = 0; - } -}
@@ -1,4 +0,0 @@
-mod cpu_spqlios; -mod generic_cggi; -mod generic_lut; -mod generic_serialization;
@@ -1,514 +0,0 @@
-use std::{collections::HashMap, time::Instant, usize}; - -use backend::hal::{ - api::{ - ScratchAvailable, TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, - TakeVecZnxSlice, VecZnxAddInplace, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAutomorphismInplace, VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxDftCopy, VecZnxDftToVecZnxBigTmpA, - VecZnxNegateInplace, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, - VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, - }, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, -}; -use sampling::source::Source; - -use crate::{ - BlindRotationKeyCGGI, BlindRotationKeyCGGIExec, BlindRotationKeyCGGIExecLayoutFamily, CCGIBlindRotationFamily, GLWEOps, - Infos, LookUpTable, LookUpTableRotationDirection, TakeGGLWE, TakeGLWECt, cggi_blind_rotate, - layouts::{ - AutomorphismKey, GGSWCiphertext, GLWECiphertext, GLWESecret, GLWETensorKey, LWECiphertext, LWESecret, - prepared::{AutomorphismKeyExec, GLWESecretExec, GLWETensorKeyExec}, - }, -}; - -use crate::trait_families::{ - AutomorphismKeyEncryptSkFamily, GGSWEncryptSkFamily, GLWESecretExecModuleFamily, GLWETensorKeyEncryptSkFamily, - GLWETraceModuleFamily, -}; - -pub struct CircuitBootstrappingKeyCGGI<D: Data> { - pub(crate) brk: BlindRotationKeyCGGI<D>, - pub(crate) tsk: GLWETensorKey<Vec<u8>>, - pub(crate) atk: HashMap<i64, AutomorphismKey<Vec<u8>>>, -} - -impl CircuitBootstrappingKeyCGGI<Vec<u8>> { - pub fn generate<DLwe, DGlwe, B: Backend>( - module: &Module<B>, - basek: usize, - sk_lwe: &LWESecret<DLwe>, - sk_glwe: &GLWESecret<DGlwe>, - k_brk: usize, - rows_brk: usize, - k_trace: usize, - rows_trace: usize, - k_tsk: usize, - rows_tsk: usize, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, - ) -> Self - where - Module<B>: GGSWEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> - + VecZnxAddScalarInplace - + AutomorphismKeyEncryptSkFamily<B> - + VecZnxAutomorphism - + VecZnxSwithcDegree - + GLWETensorKeyEncryptSkFamily<B>, - DLwe: DataRef, - DGlwe: DataRef, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<B> + TakeVecZnxBig<B>, - { - let mut auto_keys: HashMap<i64, AutomorphismKey<Vec<u8>>> = HashMap::new(); - let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(&module); - gal_els.iter().for_each(|gal_el| { - let mut key: AutomorphismKey<Vec<u8>> = - AutomorphismKey::alloc(sk_glwe.n(), basek, k_trace, rows_trace, 1, sk_glwe.rank()); - key.encrypt_sk( - &module, *gal_el, &sk_glwe, source_xa, source_xe, sigma, scratch, - ); - auto_keys.insert(*gal_el, key); - }); - - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); - - let mut brk: BlindRotationKeyCGGI<Vec<u8>> = BlindRotationKeyCGGI::alloc( - sk_glwe.n(), - sk_lwe.n(), - basek, - k_brk, - rows_brk, - sk_glwe.rank(), - ); - brk.generate_from_sk( - module, - &sk_glwe_exec, - sk_lwe, - source_xa, - source_xe, - sigma, - scratch, - ); - - let mut tsk: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(sk_glwe.n(), basek, k_tsk, rows_tsk, 1, sk_glwe.rank()); - tsk.encrypt_sk(module, &sk_glwe, source_xa, source_xe, sigma, scratch); - - Self { - brk, - atk: auto_keys, - tsk, - } - } -} - -pub struct CircuitBootstrappingKeyCGGIExec<D: Data, B: Backend> { - pub(crate) brk: BlindRotationKeyCGGIExec<D, B>, - pub(crate) tsk: GLWETensorKeyExec<Vec<u8>, B>, - pub(crate) atk: HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>>, -} - -impl<B: Backend> CircuitBootstrappingKeyCGGIExec<Vec<u8>, B> { - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &CircuitBootstrappingKeyCGGI<DataOther>, - scratch: &mut Scratch<B>, - ) -> CircuitBootstrappingKeyCGGIExec<Vec<u8>, B> - where - Module<B>: BlindRotationKeyCGGIExecLayoutFamily<B> + VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let brk: BlindRotationKeyCGGIExec<Vec<u8>, B> = BlindRotationKeyCGGIExec::from(module, &other.brk, scratch); - let tsk: GLWETensorKeyExec<Vec<u8>, B> = GLWETensorKeyExec::from(module, &other.tsk, scratch); - let mut atk: HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); - for (key, value) in &other.atk { - atk.insert(*key, AutomorphismKeyExec::from(module, value, scratch)); - } - CircuitBootstrappingKeyCGGIExec { brk, tsk, atk } - } -} - -pub trait CGGICircuitBootstrapFamily<B: Backend> = VecZnxRotateInplace - + VecZnxNormalizeInplace<B> - + VecZnxNormalizeTmpBytes - + CCGIBlindRotationFamily<B> - + VecZnxSwithcDegree - + VecZnxBigAutomorphismInplace<B> - + VecZnxRshInplace - + VecZnxDftCopy<B> - + VecZnxDftToVecZnxBigTmpA<B> - + VecZnxSub - + VecZnxAddInplace - + VecZnxNegateInplace - + VecZnxCopy - + VecZnxSubABInplace - + GLWETraceModuleFamily<B> - + VecZnxRotateInplace - + VecZnxAutomorphismInplace - + VecZnxBigSubSmallBInplace<B>; - -pub fn circuit_bootstrap_to_constant_cggi<DRes, DLwe, DBrk, B: Backend>( - module: &Module<B>, - res: &mut GGSWCiphertext<DRes>, - lwe: &LWECiphertext<DLwe>, - log_domain: usize, - extension_factor: usize, - key: &CircuitBootstrappingKeyCGGIExec<DBrk, B>, - scratch: &mut Scratch<B>, -) where - DRes: DataMut, - DLwe: DataRef, - DBrk: DataRef, - Module<B>: CGGICircuitBootstrapFamily<B>, - B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, - Scratch<B>: TakeVecZnx - + TakeVecZnxDftSlice<B> - + TakeVecZnxBig<B> - + TakeVecZnxDft<B> - + TakeMatZnx - + ScratchAvailable - + TakeVecZnxSlice, -{ - circuit_bootstrap_core_cggi( - false, - module, - 0, - res, - lwe, - log_domain, - extension_factor, - key, - scratch, - ); -} - -pub fn circuit_bootstrap_to_exponent_cggi<DRes, DLwe, DBrk, B: Backend>( - module: &Module<B>, - log_gap_out: usize, - res: &mut GGSWCiphertext<DRes>, - lwe: &LWECiphertext<DLwe>, - log_domain: usize, - extension_factor: usize, - key: &CircuitBootstrappingKeyCGGIExec<DBrk, B>, - scratch: &mut Scratch<B>, -) where - DRes: DataMut, - DLwe: DataRef, - DBrk: DataRef, - Module<B>: CGGICircuitBootstrapFamily<B>, - B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, - Scratch<B>: TakeVecZnx - + TakeVecZnxDftSlice<B> - + TakeVecZnxBig<B> - + TakeVecZnxDft<B> - + TakeMatZnx - + ScratchAvailable - + TakeVecZnxSlice, -{ - circuit_bootstrap_core_cggi( - true, - module, - log_gap_out, - res, - lwe, - log_domain, - extension_factor, - key, - scratch, - ); -} - -pub fn circuit_bootstrap_core_cggi<DRes, DLwe, DBrk, B: Backend>( - to_exponent: bool, - module: &Module<B>, - log_gap_out: usize, - res: &mut GGSWCiphertext<DRes>, - lwe: &LWECiphertext<DLwe>, - log_domain: usize, - extension_factor: usize, - key: &CircuitBootstrappingKeyCGGIExec<DBrk, B>, - scratch: &mut Scratch<B>, -) where - DRes: DataMut, - DLwe: DataRef, - DBrk: DataRef, - Module<B>: CGGICircuitBootstrapFamily<B>, - B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, - Scratch<B>: TakeGGLWE<B> - + TakeVecZnxDftSlice<B> - + TakeVecZnxBig<B> - + TakeVecZnxDft<B> - + TakeVecZnx - + ScratchAvailable - + TakeVecZnxSlice, -{ - #[cfg(debug_assertions)] - { - use crate::Infos; - - assert_eq!(res.n(), key.brk.n()); - assert_eq!(lwe.basek(), key.brk.basek()); - assert_eq!(res.basek(), key.brk.basek()); - } - - let n: usize = res.n(); - let basek: usize = res.basek(); - let rows: usize = res.rows(); - let rank: usize = res.rank(); - let k: usize = res.k(); - - let alpha: usize = rows.next_power_of_two(); - - let mut f: Vec<i64> = vec![0i64; (1 << log_domain) * alpha]; - - if to_exponent { - (0..rows).for_each(|i| { - f[i] = 1 << (basek * (rows - 1 - i)); - }); - } else { - (0..1 << log_domain).for_each(|j| { - (0..rows).for_each(|i| { - f[j * alpha + i] = j as i64 * (1 << (basek * (rows - 1 - i))); - }); - }); - } - - // Lut precision, basically must be able to hold the decomposition power basis of the GGSW - let mut lut: LookUpTable = LookUpTable::alloc(n, basek, basek * rows, extension_factor); - lut.set(module, &f, basek * rows); - - if to_exponent { - lut.set_rotation_direction(LookUpTableRotationDirection::Right); - } - - // TODO: separate GGSW k from output of blind rotation k - let (mut res_glwe, scratch1) = scratch.take_glwe_ct(n, basek, k, rank); - let (mut tmp_gglwe, scratch2) = scratch1.take_gglwe(n, basek, k, rows, 1, rank, rank); - - let now: Instant = Instant::now(); - cggi_blind_rotate(module, &mut res_glwe, &lwe, &lut, &key.brk, scratch2); - println!("cggi_blind_rotate: {} ms", now.elapsed().as_millis()); - - let gap: usize = 2 * lut.drift / lut.extension_factor(); - - let log_gap_in: usize = (usize::BITS - (gap * alpha - 1).leading_zeros()) as _; - - (0..rows).for_each(|i| { - let mut tmp_glwe: GLWECiphertext<&mut [u8]> = tmp_gglwe.at_mut(i, 0); - - if to_exponent { - let now: Instant = Instant::now(); - - // Isolates i-th LUT and moves coefficients according to requested gap. - post_process( - module, - &mut tmp_glwe, - &res_glwe, - log_gap_in, - log_gap_out, - log_domain, - &key.atk, - scratch2, - ); - println!("post_process: {} ms", now.elapsed().as_millis()); - } else { - tmp_glwe.trace(module, 0, module.log_n(), &res_glwe, &key.atk, scratch2); - } - - if i < rows { - res_glwe.rotate_inplace(module, -(gap as i64)); - } - }); - - // Expands GGLWE to GGSW using GGLWE(s^2) - res.from_gglwe(module, &tmp_gglwe, &key.tsk, scratch2); -} - -fn post_process<DataRes, DataA, B: Backend>( - module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - a: &GLWECiphertext<DataA>, - log_gap_in: usize, - log_gap_out: usize, - log_domain: usize, - auto_keys: &HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>>, - scratch: &mut Scratch<B>, -) where - DataRes: DataMut, - DataA: DataRef, - Module<B>: CGGICircuitBootstrapFamily<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, -{ - let log_n: usize = module.log_n(); - - let mut cts: HashMap<usize, GLWECiphertext<Vec<u8>>> = HashMap::new(); - - // First partial trace, vanishes all coefficients which are not multiples of gap_in - // [1, 1, 1, 1, 0, 0, 0, ..., 0, 0, -1, -1, -1, -1] -> [1, 0, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0] - res.trace( - module, - module.log_n() - log_gap_in as usize + 1, - log_n, - &a, - auto_keys, - scratch, - ); - - // TODO: optimize with packing and final partial trace - // If gap_out < gap_in, then we need to repack, i.e. reduce the cap between coefficients. - if log_gap_in != log_gap_out { - let steps: i32 = 1 << log_domain; - (0..steps).for_each(|i| { - if i != 0 { - res.rotate_inplace(module, -(1 << log_gap_in)); - } - cts.insert(i as usize * (1 << log_gap_out), res.clone()); - }); - - let now: Instant = Instant::now(); - pack(module, &mut cts, log_gap_out, auto_keys, scratch); - println!("pack: {} ms", now.elapsed().as_millis()); - let packed: GLWECiphertext<Vec<u8>> = cts.remove(&0).unwrap(); - res.trace( - module, - log_n - log_gap_out, - log_n, - &packed, - auto_keys, - scratch, - ); - } -} - -pub fn pack<D: DataMut, B: Backend>( - module: &Module<B>, - cts: &mut HashMap<usize, GLWECiphertext<D>>, - log_gap_out: usize, - auto_keys: &HashMap<i64, AutomorphismKeyExec<Vec<u8>, B>>, - scratch: &mut Scratch<B>, -) where - Module<B>: CGGICircuitBootstrapFamily<B>, - Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, -{ - let log_n: usize = module.log_n(); - - let basek: usize = cts.get(&0).unwrap().basek(); - let k: usize = cts.get(&0).unwrap().k(); - let rank: usize = cts.get(&0).unwrap().rank(); - - (0..log_n - log_gap_out).for_each(|i| { - let now: Instant = Instant::now(); - - let t = 16.min(1 << (log_n - 1 - i)); - - let auto_key: &AutomorphismKeyExec<Vec<u8>, B>; - if i == 0 { - auto_key = auto_keys.get(&-1).unwrap() - } else { - auto_key = auto_keys.get(&module.galois_element(1 << (i - 1))).unwrap(); - } - - (0..t).for_each(|j| { - let mut a: Option<GLWECiphertext<D>> = cts.remove(&j); - let mut b: Option<GLWECiphertext<D>> = cts.remove(&(j + t)); - - combine( - module, - basek, - k, - rank, - a.as_mut(), - b.as_mut(), - i, - auto_key, - scratch, - ); - - if let Some(a) = a { - cts.insert(j, a); - } else if let Some(b) = b { - cts.insert(j, b); - } - }); - - println!("combine: {} us", now.elapsed().as_micros()); - }); -} - -fn combine<A: DataMut, D: DataMut, DataAK: DataRef, B: Backend>( - module: &Module<B>, - basek: usize, - k: usize, - rank: usize, - a: Option<&mut GLWECiphertext<A>>, - b: Option<&mut GLWECiphertext<D>>, - i: usize, - auto_key: &AutomorphismKeyExec<DataAK, B>, - scratch: &mut Scratch<B>, -) where - Module<B>: CGGICircuitBootstrapFamily<B>, - Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, -{ - // Goal is to evaluate: a = a + b*X^t + phi(a - b*X^t)) - // We also use the identity: AUTO(a * X^t, g) = -X^t * AUTO(a, g) - // where t = 2^(log_n - i - 1) and g = 5^{2^(i - 1)} - // Different cases for wether a and/or b are zero. - // - // Implicite RSH without modulus switch, introduces extra I(X) * Q/2 on decryption. - // Necessary so that the scaling of the plaintext remains constant. - // It however is ok to do so here because coefficients are eventually - // either mapped to garbage or twice their value which vanishes I(X) - // since 2*(I(X) * Q/2) = I(X) * Q = 0 mod Q. - if let Some(a) = a { - let n: usize = a.n(); - let log_n: usize = (u64::BITS - (n - 1).leading_zeros()) as _; - let t: i64 = 1 << (log_n - i - 1); - - if let Some(b) = b { - let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(n, basek, k, rank); - - // a = a * X^-t - a.rotate_inplace(module, -t); - - // tmp_b = a * X^-t - b - tmp_b.sub(module, a, b); - tmp_b.rsh(module, 1); - - // a = a * X^-t + b - a.add_inplace(module, b); - a.rsh(module, 1); - - tmp_b.normalize_inplace(module, scratch_1); - - // tmp_b = phi(a * X^-t - b) - tmp_b.automorphism_inplace(module, auto_key, scratch_1); - - // a = a * X^-t + b - phi(a * X^-t - b) - a.sub_inplace_ab(module, &tmp_b); - a.normalize_inplace(module, scratch_1); - - // a = a + b * X^t - phi(a * X^-t - b) * X^t - // = a + b * X^t - phi(a * X^-t - b) * - phi(X^t) - // = a + b * X^t + phi(a - b * X^t) - a.rotate_inplace(module, t); - } else { - a.rsh(module, 1); - // a = a + phi(a) - a.automorphism_add_inplace(module, auto_key, scratch); - } - } else { - if let Some(b) = b { - let n: usize = b.n(); - let log_n: usize = (u64::BITS - (n - 1).leading_zeros()) as _; - let t: i64 = 1 << (log_n - i - 1); - - let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(n, basek, k, rank); - tmp_b.rotate(module, t, b); - tmp_b.rsh(module, 1); - - // a = (b* X^t - phi(b* X^t)) - b.automorphism_sub_ba(module, &tmp_b, auto_key, scratch_1); - } - } -}
@@ -1,6 +0,0 @@
-mod circuit_bootstrapping; - -pub use circuit_bootstrapping::*; - -#[cfg(test)] -mod test_fft64;
@@ -1,63 +1,61 @@
use std::time::Instant; -use backend::{ - hal::{ - api::{ - ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, - VecZnxEncodeCoeffsi64, VecZnxFillUniform, VecZnxNormalizeInplace, VecZnxRotateInplace, VecZnxStd, VecZnxSwithcDegree, - VmpPMatAlloc, VmpPMatPrepare, ZnxView, ZnxViewMut, - }, - layouts::{Backend, Module, ScalarZnx, ScratchOwned}, - oep::{ - ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, - TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, - }, +use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpPPolAlloc, SvpPrepare, VecZnxAddNormal, VecZnxAddScalarInplace, + VecZnxAutomorphism, VecZnxFillUniform, VecZnxNormalizeInplace, VecZnxRotateInplace, VecZnxSwithcDegree, VmpPMatAlloc, + VmpPMatPrepare, ZnxView, ZnxViewMut, }, - implementation::cpu_spqlios::FFT64, + layouts::{Backend, Module, ScalarZnx, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl, + TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, + }, }; use sampling::source::Source; -use crate::{ - BlindRotationKeyCGGIExecLayoutFamily, - circuit_bootstrapping::circuit_bootstrapping::{ - CGGICircuitBootstrapFamily, CircuitBootstrappingKeyCGGI, CircuitBootstrappingKeyCGGIExec, - circuit_bootstrap_to_constant_cggi, circuit_bootstrap_to_exponent_cggi, +use crate::tfhe::{ + blind_rotation::{ + BlincRotationExecute, BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, + BlindRotationKeyPrepared, }, - layouts::{ - GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWEPlaintext, LWESecret, - prepared::{GGSWCiphertextExec, GLWESecretExec}, + circuit_bootstrapping::{ + CircuitBootstrapFamily, CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyPrepared, + CirtuitBootstrappingExecute, }, }; -use crate::trait_families::{ - AutomorphismKeyEncryptSkFamily, GGSWAssertNoiseFamily, GGSWEncryptSkFamily, GLWEDecryptFamily, GLWETensorKeyEncryptSkFamily, +use core::{ + layouts::prepared::PrepareAlloc, + trait_families::{ + GGLWEAutomorphismKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWAssertNoiseFamily, GGSWEncryptSkFamily, + GLWEDecryptFamily, + }, }; -#[test] -fn test_to_exponent() { - let module: Module<FFT64> = Module::<FFT64>::new(256); - to_exponent(&module); -} +use core::layouts::{ + GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWEPlaintext, LWESecret, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared}, +}; -fn to_exponent<B: Backend>(module: &Module<B>) +pub fn test_circuit_bootstrapping_to_exponent<B: Backend, BRA: BlindRotationAlgo>(module: &Module<B>) where - Module<B>: VecZnxEncodeCoeffsi64 - + VecZnxFillUniform + Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> + GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace - + AutomorphismKeyEncryptSkFamily<B> + + GGLWEAutomorphismKeyEncryptSkFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree - + GLWETensorKeyEncryptSkFamily<B> - + BlindRotationKeyCGGIExecLayoutFamily<B> - + CGGICircuitBootstrapFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + CircuitBootstrapFamily<B> + GLWEDecryptFamily<B> + GGSWAssertNoiseFamily<B> - + VecZnxStd + VmpPMatAlloc<B> - + VmpPMatPrepare<B>, + + VmpPMatPrepare<B> + + SvpPrepare<B> + + SvpPPolAlloc<B>, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeVecZnxDftImpl<B>@@ -69,6 +67,9 @@ + TakeVecZnxBigImpl<B>
+ TakeVecZnxDftSliceImpl<B> + TakeMatZnxImpl<B> + TakeVecZnxSliceImpl<B>, + BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>, + BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>, + BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>, { let n: usize = module.n(); let basek: usize = 17;@@ -102,14 +103,14 @@
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let data: i64 = 1; let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut pt_lwe.data, 0, k_lwe_pt + 2, 0, data, k_lwe_pt); + pt_lwe.encode_i64(data, k_lwe_pt + 2); - println!("pt_lwe: {}", pt_lwe.data); + println!("pt_lwe: {}", pt_lwe); let mut ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); ct_lwe.encrypt_sk(@@ -122,7 +123,7 @@ sigma,
); let now: Instant = Instant::now(); - let cbt_key: CircuitBootstrappingKeyCGGI<Vec<u8>> = CircuitBootstrappingKeyCGGI::generate( + let cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> = CircuitBootstrappingKey::encrypt_sk( module, basek, &sk_lwe,@@ -147,18 +148,16 @@ let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw_res, rows_ggsw_res, 1, rank);
let log_gap_out = 1; - let cbt_exec: CircuitBootstrappingKeyCGGIExec<Vec<u8>, B> = - CircuitBootstrappingKeyCGGIExec::from(module, &cbt_key, scratch.borrow()); + let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> = cbt_key.prepare_alloc(module, scratch.borrow()); let now: Instant = Instant::now(); - circuit_bootstrap_to_exponent_cggi( + cbt_prepared.execute_to_exponent( module, log_gap_out, &mut res, &ct_lwe, k_lwe_pt, extension_factor, - &cbt_exec, scratch.borrow(), ); println!("CBT: {} ms", now.elapsed().as_millis());@@ -168,7 +167,7 @@ let mut pt_ggsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
pt_ggsw.at_mut(0, 0)[0] = 1; module.vec_znx_rotate_inplace(data * (1 << log_gap_out), &mut pt_ggsw.as_vec_znx_mut(), 0); - res.print_noise(module, &sk_glwe_exec, &pt_ggsw); + res.print_noise(module, &sk_glwe_prepared, &pt_ggsw); let k_glwe: usize = k_ggsw_res;@@ -179,19 +178,19 @@
ct_glwe.encrypt_sk( module, &pt_glwe, - &sk_glwe_exec, + &sk_glwe_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let res_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::from(module, &res, scratch.borrow()); + let res_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); - ct_glwe.external_product_inplace(module, &res_exec, scratch.borrow()); + ct_glwe.external_product_inplace(module, &res_prepared, scratch.borrow()); let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe); - ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_exec, scratch.borrow()); + ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_prepared, scratch.borrow()); // Parameters are set such that the first limb should be noiseless. let mut pt_want: Vec<i64> = vec![0i64; module.n()];@@ -199,31 +198,24 @@ pt_want[data as usize * (1 << log_gap_out)] = pt_glwe.data.at(0, 0)[0];
assert_eq!(pt_res.data.at(0, 0), pt_want); } -#[test] -fn test_to_constant() { - let module: Module<FFT64> = Module::<FFT64>::new(256); - to_constant(&module); -} - -fn to_constant<B: Backend>(module: &Module<B>) +pub fn test_circuit_bootstrapping_to_constant<B: Backend, BRA: BlindRotationAlgo>(module: &Module<B>) where - Module<B>: VecZnxEncodeCoeffsi64 - + VecZnxFillUniform + Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> + GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace - + AutomorphismKeyEncryptSkFamily<B> + + GGLWEAutomorphismKeyEncryptSkFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree - + GLWETensorKeyEncryptSkFamily<B> - + BlindRotationKeyCGGIExecLayoutFamily<B> - + CGGICircuitBootstrapFamily<B> + + GGLWETensorKeyEncryptSkFamily<B> + + CircuitBootstrapFamily<B> + GLWEDecryptFamily<B> + GGSWAssertNoiseFamily<B> - + VecZnxStd + VmpPMatAlloc<B> - + VmpPMatPrepare<B>, + + VmpPMatPrepare<B> + + SvpPrepare<B> + + SvpPPolAlloc<B>, B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B> + TakeVecZnxDftImpl<B>@@ -235,6 +227,9 @@ + TakeVecZnxBigImpl<B>
+ TakeVecZnxDftSliceImpl<B> + TakeMatZnxImpl<B> + TakeVecZnxSliceImpl<B>, + BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>, + BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>, + BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>, { let n = module.n(); let basek: usize = 14;@@ -268,14 +263,14 @@
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let data: i64 = 1; let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut pt_lwe.data, 0, k_lwe_pt + 2, 0, data, k_lwe_pt); + pt_lwe.encode_i64(data, k_lwe_pt + 2); - println!("pt_lwe: {}", pt_lwe.data); + println!("pt_lwe: {}", pt_lwe); let mut ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); ct_lwe.encrypt_sk(@@ -288,7 +283,7 @@ sigma,
); let now: Instant = Instant::now(); - let cbt_key: CircuitBootstrappingKeyCGGI<Vec<u8>> = CircuitBootstrappingKeyCGGI::generate( + let cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> = CircuitBootstrappingKey::encrypt_sk( module, basek, &sk_lwe,@@ -311,17 +306,15 @@ let rows_ggsw_res: usize = 3;
let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw_res, rows_ggsw_res, 1, rank); - let cbt_exec: CircuitBootstrappingKeyCGGIExec<Vec<u8>, B> = - CircuitBootstrappingKeyCGGIExec::from(module, &cbt_key, scratch.borrow()); + let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> = cbt_key.prepare_alloc(module, scratch.borrow()); let now: Instant = Instant::now(); - circuit_bootstrap_to_constant_cggi( + cbt_prepared.execute_to_constant( module, &mut res, &ct_lwe, k_lwe_pt, extension_factor, - &cbt_exec, scratch.borrow(), ); println!("CBT: {} ms", now.elapsed().as_millis());@@ -330,7 +323,7 @@ // X^{data * 2^log_gap_out}
let mut pt_ggsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); pt_ggsw.at_mut(0, 0)[0] = data; - res.print_noise(module, &sk_glwe_exec, &pt_ggsw); + res.print_noise(module, &sk_glwe_prepared, &pt_ggsw); let k_glwe: usize = k_ggsw_res;@@ -341,19 +334,19 @@
ct_glwe.encrypt_sk( module, &pt_glwe, - &sk_glwe_exec, + &sk_glwe_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let res_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::from(module, &res, scratch.borrow()); + let res_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); - ct_glwe.external_product_inplace(module, &res_exec, scratch.borrow()); + ct_glwe.external_product_inplace(module, &res_prepared, scratch.borrow()); let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe); - ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_exec, scratch.borrow()); + ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_prepared, scratch.borrow()); // Parameters are set such that the first limb should be noiseless. let mut pt_want: Vec<i64> = vec![0i64; module.n()];
@@ -1,4 +1,7 @@
-use core::layouts::{prepared::{GGSWCiphertextExec, GLWESecretExec}, GGSWCiphertext, GLWECiphertext, GLWESecret, Infos}; +use core::layouts::{ + GGSWCiphertext, GLWECiphertext, GLWESecret, Infos, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, +}; use std::hint::black_box; use backend::{@@ -63,7 +66,7 @@ let mut source_xa = Source::new([0u8; 32]);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_dft: GLWESecretExec<Vec<u8>, FFT64> = GLWESecretExec::from(&module, &sk); + let sk_dft: GLWESecretPrepared<Vec<u8>, FFT64> = sk.prepare_alloc(&module, scratch.borrow()); ct_ggsw.encrypt_sk( &module,@@ -84,10 +87,10 @@ sigma,
scratch.borrow(), ); - let ggsw_exec: GGSWCiphertextExec<Vec<u8>, FFT64> = GGSWCiphertextExec::from(&module, &ct_ggsw, scratch.borrow()); + let ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, FFT64> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); move || { - black_box(ct_glwe_out.external_product(&module, &ct_glwe_in, &ggsw_exec, scratch.borrow())); + black_box(ct_glwe_out.external_product(&module, &ct_glwe_in, &ggsw_prepared, scratch.borrow())); } }@@ -157,7 +160,7 @@ let mut source_xa = Source::new([0u8; 32]);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_dft: GLWESecretExec<Vec<u8>, FFT64> = GLWESecretExec::from(&module, &sk); + let sk_dft: GLWESecretPrepared<Vec<u8>, FFT64> = sk.prepare_alloc(&module, scratch.borrow()); ct_ggsw.encrypt_sk( &module,@@ -178,11 +181,11 @@ sigma,
scratch.borrow(), ); - let ggsw_exec: GGSWCiphertextExec<Vec<u8>, FFT64> = GGSWCiphertextExec::from(&module, &ct_ggsw, scratch.borrow()); + let ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, FFT64> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); move || { let scratch_borrow = scratch.borrow(); - black_box(ct_glwe.external_product_inplace(&module, &ggsw_exec, scratch_borrow)); + black_box(ct_glwe.external_product_inplace(&module, &ggsw_prepared, scratch_borrow)); } }
@@ -1,4 +1,7 @@
-use core::layouts::{prepared::{GGLWEAutomorphismKeyExec, GGLWESwitchingKeyExec, GLWESecretExec}, GGLWEAutomorphismKey, GGLWESwitchingKey, GLWECiphertext, GLWESecret, Infos}; +use core::layouts::{ + GGLWEAutomorphismKey, GGLWESwitchingKey, GLWECiphertext, GLWESecret, Infos, + prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, +}; use std::{hint::black_box, time::Duration}; use backend::{@@ -66,7 +69,7 @@ let mut source_xa = Source::new([0u8; 32]);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, FFT64> = GLWESecretExec::from(&module, &sk_in); + let sk_in_dft: GLWESecretPrepared<Vec<u8>, FFT64> = sk_in.prepare_alloc(&module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(0.5, &mut source_xs);@@ -90,10 +93,10 @@ sigma,
scratch.borrow(), ); - let ksk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, _> = GGLWEAutomorphismKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, _> = ksk.prepare_alloc(&module, scratch.borrow()); move || { - black_box(ct_out.automorphism(&module, &ct_in, &ksk_exec, scratch.borrow())); + black_box(ct_out.automorphism(&module, &ct_in, &ksk_prepared, scratch.borrow())); } }@@ -161,7 +164,7 @@ let mut source_xa: Source = Source::new([0u8; 32]);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, FFT64> = GLWESecretExec::from(&module, &sk_in); + let sk_in_dft: GLWESecretPrepared<Vec<u8>, FFT64> = sk_in.prepare_alloc(&module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_out.fill_ternary_prob(0.5, &mut source_xs);@@ -185,10 +188,10 @@ sigma,
scratch.borrow(), ); - let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, FFT64> = GGLWESwitchingKeyExec::from(&module, &ksk, scratch.borrow()); + let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, FFT64> = ksk.prepare_alloc(&module, scratch.borrow()); move || { - black_box(ct.keyswitch_inplace(&module, &ksk_exec, scratch.borrow())); + black_box(ct.keyswitch_inplace(&module, &ksk_prepared, scratch.borrow())); } }
@@ -4,7 +4,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - layouts::{GGLWEAutomorphismKey, GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, + layouts::{GGLWEAutomorphismKey, GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyPrepared}, trait_families::GLWEKeyswitchFamily, };@@ -46,7 +46,7 @@ pub fn automorphism<'a, DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxAutomorphismInplace,@@ -120,7 +120,7 @@
pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxAutomorphismInplace,
@@ -6,7 +6,7 @@
use crate::{ layouts::{ GGSWCiphertext, GLWECiphertext, Infos, - prepared::{GGLWEAutomorphismKeyExec, GGLWETensorKeyExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared}, }, trait_families::{GGSWKeySwitchFamily, GLWEKeyswitchFamily}, };@@ -60,8 +60,8 @@ pub fn automorphism<DataLhs: DataRef, DataAk: DataRef, DataTsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - auto_key: &GGLWEAutomorphismKeyExec<DataAk, B>, - tensor_key: &GGLWETensorKeyExec<DataTsk, B>, + auto_key: &GGLWEAutomorphismKeyPrepared<DataAk, B>, + tensor_key: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,@@ -117,8 +117,8 @@
pub fn automorphism_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - auto_key: &GGLWEAutomorphismKeyExec<DataKsk, B>, - tensor_key: &GGLWETensorKeyExec<DataTsk, B>, + auto_key: &GGLWEAutomorphismKeyPrepared<DataKsk, B>, + tensor_key: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,@@ -134,7 +134,7 @@ fn automorphism_internal<DataLhs: DataRef, DataAk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - auto_key: &GGLWEAutomorphismKeyExec<DataAk, B>, + auto_key: &GGLWEAutomorphismKeyPrepared<DataAk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxAutomorphismInplace + VecZnxNormalizeTmpBytes,
@@ -7,7 +7,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig},
}; use crate::{ - layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, + layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyPrepared}, trait_families::GLWEKeyswitchFamily, };@@ -49,7 +49,7 @@ pub fn automorphism<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphismInplace,@@ -64,7 +64,7 @@
pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxAutomorphismInplace,@@ -80,7 +80,7 @@ pub fn automorphism_add<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B>,@@ -102,7 +102,7 @@
pub fn automorphism_add_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B>,@@ -118,7 +118,7 @@ pub fn automorphism_sub_ab<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallAInplace<B>,@@ -140,7 +140,7 @@
pub fn automorphism_sub_ab_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallAInplace<B>,@@ -156,7 +156,7 @@ pub fn automorphism_sub_ba<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallBInplace<B>,@@ -178,7 +178,7 @@
pub fn automorphism_sub_ba_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallBInplace<B>,
@@ -5,7 +5,7 @@ };
use crate::{ TakeGLWECt, - layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::GLWEToLWESwitchingKeyExec}, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::GLWEToLWESwitchingKeyPrepared}, }; use crate::trait_families::GLWEKeyswitchFamily;@@ -50,7 +50,7 @@ pub fn from_glwe<DGlwe, DKs, B: Backend>(
&mut self, module: &Module<B>, a: &GLWECiphertext<DGlwe>, - ks: &GLWEToLWESwitchingKeyExec<DKs, B>, + ks: &GLWEToLWESwitchingKeyPrepared<DKs, B>, scratch: &mut Scratch<B>, ) where DGlwe: DataRef,
@@ -5,7 +5,7 @@ };
use crate::{ TakeGLWECt, - layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWEToGLWESwitchingKeyExec}, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWEToGLWESwitchingKeyPrepared}, }; use crate::trait_families::GLWEKeyswitchFamily;@@ -33,7 +33,7 @@ pub fn from_lwe<DLwe, DKsk, B: Backend>(
&mut self, module: &Module<B>, lwe: &LWECiphertext<DLwe>, - ksk: &LWEToGLWESwitchingKeyExec<DKsk, B>, + ksk: &LWEToGLWESwitchingKeyPrepared<DKsk, B>, scratch: &mut Scratch<B>, ) where DLwe: DataRef,
@@ -7,7 +7,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - layouts::{GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + layouts::{GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretPrepared}, trait_families::GLWEDecryptFamily, };@@ -27,7 +27,7 @@ pub fn decrypt<DataPt: DataMut, DataSk: DataRef, B: Backend>(
&self, module: &Module<B>, pt: &mut GLWEPlaintext<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEDecryptFamily<B>,
@@ -1,7 +1,7 @@
use std::io::{Read, Result, Write}; #[derive(Clone, Copy, Debug)] -pub(crate) enum Distribution { +pub enum Distribution { TernaryFixed(usize), // Ternary with fixed Hamming weight TernaryProb(f64), // Ternary with probabilistic Hamming weight BinaryFixed(usize), // Binary with fixed Hamming weight
@@ -8,19 +8,19 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, + TakeGLWESecret, TakeGLWESecretPrepared, layouts::{ GLWESecret, Infos, compressed::{GGLWEAutomorphismKeyCompressed, GGLWESwitchingKeyCompressed}, }, }; -use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWEAutomorphismKeyCompressed<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize where - Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) }@@ -41,8 +41,8 @@ Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B>
+ VecZnxSwithcDegree + VecZnxAutomorphism + VecZnxAddScalarInplace - + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + TakeVecZnx, { #[cfg(debug_assertions)] {
@@ -7,7 +7,7 @@
use crate::{ TakeGLWEPt, encryption::glwe_encrypt_sk_internal, - layouts::{GGLWECiphertext, Infos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretExec}, + layouts::{GGLWECiphertext, Infos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretPrepared}, }; use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily};@@ -26,7 +26,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, seed: [u8; 32], source_xe: &mut Source, sigma: f64,
@@ -5,13 +5,14 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecretExec, + TakeGLWESecretPrepared, layouts::{ - GGLWECiphertext, GLWESecret, GGLWESwitchingKey, Infos, compressed::GGLWESwitchingKeyCompressed, prepared::GLWESecretExec, + GGLWECiphertext, GGLWESwitchingKey, GLWESecret, Infos, compressed::GGLWESwitchingKeyCompressed, + prepared::GLWESecretPrepared, }, }; -use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWESwitchingKeyCompressed<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(@@ -23,11 +24,11 @@ rank_in: usize,
rank_out: usize, ) -> usize where - Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) + ScalarZnx::alloc_bytes(n, rank_in) - + GLWESecretExec::bytes_of(module, n, rank_out) + + GLWESecretPrepared::bytes_of(module, n, rank_out) } }@@ -43,8 +44,9 @@ sigma: f64,
scratch: &mut Scratch<B>, ) where Module<B>: - GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, + GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: + ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + ScratchAvailable + TakeVecZnx, { #[cfg(debug_assertions)] {@@ -85,7 +87,7 @@ i,
); }); - let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); + let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_prepared(n, sk_out.rank()); { let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); (0..sk_out.rank()).for_each(|i| {
@@ -8,17 +8,17 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GGLWETensorKey, GLWESecret, Infos, compressed::GGLWETensorKeyCompressed}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{GGLWETensorKey, GLWESecret, Infos, compressed::GGLWETensorKeyCompressed, prepared::Prepare}, trait_families::GLWEDecryptFamily, }; -use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWETensorKeyCompressed<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize where - Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GGLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank) }@@ -34,8 +34,10 @@ source_xe: &mut Source,
sigma: f64, scratch: &mut Scratch<B>, ) where - Module<B>: GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, + Module<B>: + GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: + ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretPrepared<B> + TakeScalarZnx + TakeVecZnx, { #[cfg(debug_assertions)] {@@ -46,8 +48,8 @@
let n: usize = sk.n(); let rank: usize = self.rank(); - let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); - sk_dft_prep.prepare(module, &sk); + let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_prepared(n, rank); + sk_dft_prep.prepare(module, &sk, scratch1); let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1);
@@ -7,7 +7,7 @@
use crate::{ TakeGLWEPt, encryption::glwe_encrypt_sk_internal, - layouts::{GGSWCiphertext, Infos, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, + layouts::{GGSWCiphertext, Infos, compressed::GGSWCiphertextCompressed, prepared::GLWESecretPrepared}, }; use crate::trait_families::GGSWEncryptSkFamily;@@ -26,7 +26,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, seed_xa: [u8; 32], source_xe: &mut Source, sigma: f64,
@@ -6,7 +6,7 @@ use sampling::source::Source;
use crate::{ encryption::glwe_ct::glwe_encrypt_sk_internal, - layouts::{GLWECiphertext, GLWEPlaintext, Infos, compressed::GLWECiphertextCompressed, prepared::GLWESecretExec}, + layouts::{GLWECiphertext, GLWEPlaintext, Infos, compressed::GLWECiphertextCompressed, prepared::GLWESecretPrepared}, }; use crate::trait_families::GLWEEncryptSkFamily;@@ -25,7 +25,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &GLWEPlaintext<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, seed_xa: [u8; 32], source_xe: &mut Source, sigma: f64,@@ -49,7 +49,7 @@ pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, seed_xa: [u8; 32], source_xe: &mut Source, sigma: f64,
@@ -8,16 +8,16 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GGLWEAutomorphismKey, GLWESecret, GGLWESwitchingKey, Infos}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{GGLWEAutomorphismKey, GGLWESwitchingKey, GLWESecret, Infos}, }; -use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWEAutomorphismKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize where - Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank) }@@ -42,8 +42,8 @@ Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B>
+ VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace - + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + TakeVecZnx, { #[cfg(debug_assertions)] {
@@ -9,7 +9,7 @@ use sampling::source::Source;
use crate::{ TakeGLWEPt, - layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretPrepared}, }; use crate::trait_families::GGLWEEncryptSkFamily;@@ -33,7 +33,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,
@@ -5,11 +5,11 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecretExec, - layouts::{GGLWECiphertext, GLWESecret, GGLWESwitchingKey, Infos, prepared::GLWESecretExec}, + TakeGLWESecretPrepared, + layouts::{GGLWECiphertext, GGLWESwitchingKey, GLWESecret, Infos, prepared::GLWESecretPrepared}, }; -use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWESwitchingKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(@@ -21,11 +21,11 @@ rank_in: usize,
rank_out: usize, ) -> usize where - Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1)) + ScalarZnx::alloc_bytes(n, rank_in) - + GLWESecretExec::bytes_of(module, n, rank_out) + + GLWESecretPrepared::bytes_of(module, n, rank_out) } pub fn encrypt_pk_scratch_space<B: Backend>(@@ -52,8 +52,9 @@ sigma: f64,
scratch: &mut Scratch<B>, ) where Module<B>: - GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx, + GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: + ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + ScratchAvailable + TakeVecZnx, { #[cfg(debug_assertions)] {@@ -94,7 +95,7 @@ i,
); }); - let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank()); + let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_prepared(n, sk_out.rank()); { let (mut tmp, _) = scratch2.take_scalar_znx(n, 1); (0..sk_out.rank()).for_each(|i| {
@@ -8,19 +8,22 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GGLWETensorKey, GLWESecret, GGLWESwitchingKey, Infos, prepared::GLWESecretExec}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{ + GGLWESwitchingKey, GGLWETensorKey, GLWESecret, Infos, + prepared::{GLWESecretPrepared, Prepare}, + }, trait_families::GLWEDecryptFamily, }; -use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWETensorKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GGLWETensorKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize where - Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWETensorKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { - GLWESecretExec::bytes_of(module, n, rank) + GLWESecretPrepared::bytes_of(module, n, rank) + module.vec_znx_dft_alloc_bytes(n, rank, 1) + module.vec_znx_big_alloc_bytes(n, 1, 1) + module.vec_znx_dft_alloc_bytes(n, 1, 1)@@ -39,8 +42,10 @@ source_xe: &mut Source,
sigma: f64, scratch: &mut Scratch<B>, ) where - Module<B>: GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx, + Module<B>: + GGLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: + ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretPrepared<B> + TakeScalarZnx + TakeVecZnx, { #[cfg(debug_assertions)] {@@ -52,8 +57,8 @@ let n: usize = sk.n();
let rank: usize = self.rank(); - let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank); - sk_dft_prep.prepare(module, &sk); + let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_prepared(n, rank); + sk_dft_prep.prepare(module, &sk, scratch1); let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1);
@@ -6,7 +6,7 @@ use sampling::source::Source;
use crate::{ TakeGLWEPt, - layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GLWESecretExec}, + layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GLWESecretPrepared}, }; use crate::trait_families::GLWEEncryptSkFamily;@@ -31,7 +31,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &ScalarZnx<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,
@@ -13,7 +13,7 @@ SIX_SIGMA,
dist::Distribution, layouts::{ GLWECiphertext, GLWEPlaintext, Infos, - prepared::{GLWEPublicKeyExec, GLWESecretExec}, + prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared}, }, trait_families::{GLWEEncryptPkFamily, GLWEEncryptSkFamily}, };@@ -42,7 +42,7 @@ pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &GLWEPlaintext<DataPt>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,@@ -78,7 +78,7 @@
pub fn encrypt_zero_sk<DataSk: DataRef, B: Backend>( &mut self, module: &Module<B>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,@@ -113,7 +113,7 @@ pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,@@ -143,7 +143,7 @@ pub fn encrypt_pk<DataPt: DataRef, DataPk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: &GLWEPlaintext<DataPt>, - pk: &GLWEPublicKeyExec<DataPk, B>, + pk: &GLWEPublicKeyPrepared<DataPk, B>, source_xu: &mut Source, source_xe: &mut Source, sigma: f64,@@ -166,7 +166,7 @@
pub fn encrypt_zero_pk<DataPk: DataRef, B: Backend>( &mut self, module: &Module<B>, - pk: &GLWEPublicKeyExec<DataPk, B>, + pk: &GLWEPublicKeyPrepared<DataPk, B>, source_xu: &mut Source, source_xe: &mut Source, sigma: f64,@@ -190,7 +190,7 @@ pub(crate) fn encrypt_pk_internal<DataPt: DataRef, DataPk: DataRef, B: Backend>(
&mut self, module: &Module<B>, pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - pk: &GLWEPublicKeyExec<DataPk, B>, + pk: &GLWEPublicKeyPrepared<DataPk, B>, source_xu: &mut Source, source_xe: &mut Source, sigma: f64,@@ -283,7 +283,7 @@ ct: &mut VecZnx<DataCt>,
cols: usize, compressed: bool, pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,
@@ -7,7 +7,7 @@ use sampling::source::Source;
use crate::{ dist::Distribution, - layouts::{GLWECiphertext, GLWEPublicKey, Infos, prepared::GLWESecretExec}, + layouts::{GLWECiphertext, GLWEPublicKey, Infos, prepared::GLWESecretPrepared}, }; use crate::trait_families::GLWEEncryptSkFamily;@@ -16,7 +16,7 @@ impl<D: DataMut> GLWEPublicKey<D> {
pub fn generate_from_sk<S: DataRef, B: Backend>( &mut self, module: &Module<B>, - sk: &GLWESecretExec<S, B>, + sk: &GLWESecretPrepared<S, B>, source_xa: &mut Source, source_xe: &mut Source, sigma: f64,
@@ -8,18 +8,18 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GLWESecret, GGLWESwitchingKey, GLWEToLWESwitchingKey, LWESecret, prepared::GLWESecretExec}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{GGLWESwitchingKey, GLWESecret, GLWEToLWESwitchingKey, LWESecret, prepared::GLWESecretPrepared}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl GLWEToLWESwitchingKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { - GLWESecretExec::bytes_of(module, n, rank_in) + GLWESecretPrepared::bytes_of(module, n, rank_in) + (GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in, 1) | GLWESecret::bytes_of(n, rank_in)) } }@@ -41,8 +41,8 @@ Module<B>: GGLWESwitchingKeyEncryptSkFamily<B>
+ VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace - + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + TakeVecZnx, { #[cfg(debug_assertions)] {
@@ -8,19 +8,19 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GLWESecret, GGLWESwitchingKey, Infos, LWESecret, LWESwitchingKey, prepared::GLWESecretExec}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{GGLWESwitchingKey, GLWESecret, Infos, LWESecret, LWESwitchingKey, prepared::GLWESecretPrepared}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl LWESwitchingKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GLWESecret::bytes_of(n, 1) - + GLWESecretExec::bytes_of(module, n, 1) + + GLWESecretPrepared::bytes_of(module, n, 1) + GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, 1) } }@@ -42,8 +42,8 @@ Module<B>: GGLWESwitchingKeyEncryptSkFamily<B>
+ VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace - + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + TakeVecZnx, { #[cfg(debug_assertions)] {
@@ -8,16 +8,16 @@ };
use sampling::source::Source; use crate::{ - TakeGLWESecret, TakeGLWESecretExec, - layouts::{GLWESecret, GGLWESwitchingKey, LWESecret, LWEToGLWESwitchingKey}, + TakeGLWESecret, TakeGLWESecretPrepared, + layouts::{GGLWESwitchingKey, GLWESecret, LWESecret, LWEToGLWESwitchingKey}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; impl LWEToGLWESwitchingKey<Vec<u8>> { pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, 1, rank_out) + GLWESecret::bytes_of(n, 1) }@@ -40,8 +40,8 @@ Module<B>: GGLWESwitchingKeyEncryptSkFamily<B>
+ VecZnxAutomorphismInplace + VecZnxSwithcDegree + VecZnxAddScalarInplace - + GLWESecretExecModuleFamily<B>, - Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx, + + GLWESecretPreparedModuleFamily<B>, + Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + TakeVecZnx, { #[cfg(debug_assertions)] {
@@ -4,7 +4,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - layouts::{GGLWEAutomorphismKey, GGLWESwitchingKey, prepared::GGSWCiphertextExec}, + layouts::{GGLWEAutomorphismKey, GGLWESwitchingKey, prepared::GGSWCiphertextPrepared}, trait_families::GLWEExternalProductFamily, };@@ -46,7 +46,7 @@ pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,@@ -58,7 +58,7 @@
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,
@@ -4,7 +4,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - layouts::{GLWECiphertext, GGLWESwitchingKey, Infos, prepared::GGSWCiphertextExec}, + layouts::{GGLWESwitchingKey, GLWECiphertext, Infos, prepared::GGSWCiphertextPrepared}, trait_families::GLWEExternalProductFamily, };@@ -46,7 +46,7 @@ pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGLWESwitchingKey<DataLhs>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,@@ -94,7 +94,7 @@
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,
@@ -4,7 +4,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch},
}; use crate::{ - layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GGSWCiphertextExec}, + layouts::{GGSWCiphertext, GLWECiphertext, Infos, prepared::GGSWCiphertextPrepared}, trait_families::GLWEExternalProductFamily, };@@ -46,7 +46,7 @@ pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,@@ -105,7 +105,7 @@
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,
@@ -7,7 +7,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig},
}; use crate::{ - layouts::{GLWECiphertext, Infos, prepared::GGSWCiphertextExec}, + layouts::{GLWECiphertext, Infos, prepared::GGSWCiphertextPrepared}, trait_families::GLWEExternalProductFamily, };@@ -64,7 +64,7 @@ pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,@@ -141,7 +141,7 @@
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGSWCiphertextExec<DataRhs, B>, + rhs: &GGSWCiphertextPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEExternalProductFamily<B>,
@@ -7,7 +7,7 @@ };
use crate::{ GLWEOperations, TakeGLWECt, - layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyExec}, + layouts::{GLWECiphertext, Infos, prepared::GGLWEAutomorphismKeyPrepared}, }; use crate::trait_families::{GLWEKeyswitchFamily, GLWEPackingFamily};@@ -115,7 +115,7 @@ pub fn add<DataA: DataRef, DataAK: DataRef, B: Backend>(
&mut self, module: &Module<B>, a: Option<&GLWECiphertext<DataA>>, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,@@ -174,7 +174,7 @@ module: &Module<B>,
a: Option<&GLWECiphertext<D>>, accumulators: &mut [Accumulator], i: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,@@ -252,7 +252,7 @@ module: &Module<B>,
acc: &mut Accumulator, b: Option<&GLWECiphertext<D>>, i: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEPackingFamily<B>,
@@ -3,7 +3,7 @@
use backend::hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; use crate::{ - layouts::{GLWECiphertext, prepared::GGLWEAutomorphismKeyExec}, + layouts::{GLWECiphertext, prepared::GGLWEAutomorphismKeyPrepared}, operations::GLWEOperations, };@@ -61,7 +61,7 @@ module: &Module<B>,
start: usize, end: usize, lhs: &GLWECiphertext<DataLhs>, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWETraceModuleFamily<B>,@@ -76,7 +76,7 @@ &mut self,
module: &Module<B>, start: usize, end: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyExec<DataAK, B>>, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where Module<B>: GLWETraceModuleFamily<B>,
@@ -5,8 +5,8 @@ };
use crate::{ layouts::{ - GGLWEAutomorphismKey, GLWECiphertext, GGLWESwitchingKey, Infos, - prepared::{GGLWEAutomorphismKeyExec, GGLWESwitchingKeyExec}, + GGLWEAutomorphismKey, GGLWESwitchingKey, GLWECiphertext, Infos, + prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared}, }, trait_families::GLWEKeyswitchFamily, };@@ -49,7 +49,7 @@ pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -61,7 +61,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyExec<DataRhs, B>, + rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -112,7 +112,7 @@ pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGLWESwitchingKey<DataLhs>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -160,7 +160,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,
@@ -9,7 +9,7 @@
use crate::{ layouts::{ GGLWECiphertext, GGSWCiphertext, GLWECiphertext, Infos, - prepared::{GGLWESwitchingKeyExec, GGLWETensorKeyExec}, + prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared}, }, operations::GLWEOperations, trait_families::{GGSWKeySwitchFamily, GLWEKeyswitchFamily},@@ -97,7 +97,7 @@ pub fn from_gglwe<DataA, DataTsk, B: Backend>(
&mut self, module: &Module<B>, a: &GGLWECiphertext<DataA>, - tsk: &GGLWETensorKeyExec<DataTsk, B>, + tsk: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where DataA: DataRef,@@ -123,8 +123,8 @@ pub fn keyswitch<DataLhs: DataRef, DataKsk: DataRef, DataTsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - ksk: &GGLWESwitchingKeyExec<DataKsk, B>, - tsk: &GGLWETensorKeyExec<DataTsk, B>, + ksk: &GGLWESwitchingKeyPrepared<DataKsk, B>, + tsk: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -137,8 +137,8 @@
pub fn keyswitch_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - ksk: &GGLWESwitchingKeyExec<DataKsk, B>, - tsk: &GGLWETensorKeyExec<DataTsk, B>, + ksk: &GGLWESwitchingKeyPrepared<DataKsk, B>, + tsk: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -153,7 +153,7 @@
pub fn expand_row<DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - tsk: &GGLWETensorKeyExec<DataTsk, B>, + tsk: &GGLWETensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,@@ -278,7 +278,7 @@ fn keyswitch_internal<DataLhs: DataRef, DataKsk: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GGSWCiphertext<DataLhs>, - ksk: &GGLWESwitchingKeyExec<DataKsk, B>, + ksk: &GGLWESwitchingKeyPrepared<DataKsk, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B> + GGSWKeySwitchFamily<B> + VecZnxNormalizeTmpBytes,
@@ -7,7 +7,7 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
}; use crate::{ - layouts::{GLWECiphertext, Infos, prepared::GGLWESwitchingKeyExec}, + layouts::{GLWECiphertext, Infos, prepared::GGLWESwitchingKeyPrepared}, trait_families::GLWEKeyswitchFamily, };@@ -65,7 +65,7 @@ pub(crate) fn assert_keyswitch<B: Backend, DataLhs, DataRhs>(
&self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &Scratch<B>, ) where DataLhs: DataRef,@@ -136,7 +136,7 @@ pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self, module: &Module<B>, lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -156,7 +156,7 @@
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWESwitchingKeyExec<DataRhs, B>, + rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where Module<B>: GLWEKeyswitchFamily<B>,@@ -174,7 +174,7 @@ pub(crate) fn keyswitch_internal<B: Backend, DataRes, DataKey>(
&self, module: &Module<B>, res_dft: VecZnxDft<DataRes, B>, - rhs: &GGLWESwitchingKeyExec<DataKey, B>, + rhs: &GGLWESwitchingKeyPrepared<DataKey, B>, scratch: &mut Scratch<B>, ) -> VecZnxBig<DataRes, B> where
@@ -5,7 +5,7 @@ };
use crate::{ TakeGLWECt, - layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWESwitchingKeyExec}, + layouts::{GLWECiphertext, Infos, LWECiphertext, prepared::LWESwitchingKeyPrepared}, }; use crate::trait_families::GLWEKeyswitchFamily;@@ -32,7 +32,7 @@ pub fn keyswitch<A, DKs, B: Backend>(
&mut self, module: &Module<B>, a: &LWECiphertext<A>, - ksk: &LWESwitchingKeyExec<DKs, B>, + ksk: &LWESwitchingKeyPrepared<DKs, B>, scratch: &mut Scratch<B>, ) where A: DataRef,
@@ -7,7 +7,7 @@ };
use crate::layouts::{GLWEToLWESwitchingKey, Infos, compressed::GGLWESwitchingKeyCompressed}; -use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretPreparedModuleFamily}; #[derive(PartialEq, Eq, Clone)] pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);@@ -91,7 +91,7 @@ }
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_in: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) }
@@ -6,7 +6,7 @@
use crate::layouts::{Infos, LWESwitchingKey, compressed::GGLWESwitchingKeyCompressed}; use std::fmt; -use crate::trait_families::{Decompress, GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{Decompress, GGLWEEncryptSkFamily, GLWESecretPreparedModuleFamily}; #[derive(PartialEq, Eq, Clone)] pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);@@ -90,7 +90,7 @@ }
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) }
@@ -9,7 +9,7 @@ trait_families::Decompress,
}; use std::fmt; -use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretPreparedModuleFamily}; #[derive(PartialEq, Eq, Clone)] pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);@@ -93,7 +93,7 @@ }
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank_out: usize) -> usize where - Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretExecModuleFamily<B>, + Module<B>: GGLWEEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>, { LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) }
@@ -3,7 +3,7 @@ api::{FillUniform, Reset},
layouts::{Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo}, }; -use crate::layouts::{GLWECiphertext, GGLWESwitchingKey, Infos}; +use crate::layouts::{GGLWESwitchingKey, GLWECiphertext, Infos}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt;
@@ -1,3 +1,5 @@
+use std::fmt; + use backend::hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef}; use crate::layouts::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, Infos, SetMetaData};@@ -6,6 +8,18 @@ pub struct GLWEPlaintext<D: Data> {
pub data: VecZnx<D>, pub basek: usize, pub k: usize, +} + +impl<D: DataRef> fmt::Display for GLWEPlaintext<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWEPlaintext: basek={} k={}: {}", + self.basek(), + self.k(), + self.data + ) + } } impl<D: Data> Infos for GLWEPlaintext<D> {
@@ -13,6 +13,18 @@ pub(crate) k: usize,
pub(crate) basek: usize, } +impl<D: DataRef> LWECiphertext<D> { + pub fn data(&self) -> &VecZnx<D> { + &self.data + } +} + +impl<D: DataMut> LWECiphertext<D> { + pub fn data_mut(&mut self) -> &VecZnx<D> { + &mut self.data + } +} + impl<D: DataRef> fmt::Debug for LWECiphertext<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self)@@ -31,10 +43,7 @@ )
} } -impl<D: DataMut> Reset for LWECiphertext<D> -where - VecZnx<D>: Reset, -{ +impl<D: DataMut> Reset for LWECiphertext<D> { fn reset(&mut self) { self.data.reset(); self.basek = 0;
@@ -1,3 +1,5 @@
+use std::fmt; + use backend::hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef}; use crate::layouts::{Infos, SetMetaData};@@ -15,6 +17,18 @@ data: VecZnx::alloc(1, 1, k.div_ceil(basek)),
k: k, basek: basek, } + } +} + +impl<D: DataRef> fmt::Display for LWEPlaintext<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "LWEPlaintext: basek={} k={}: {}", + self.basek(), + self.k(), + self.data + ) } }
@@ -1,6 +1,6 @@
use backend::hal::{ - api::{ZnxInfos, ZnxZero}, - layouts::{Data, DataMut, ScalarZnx}, + api::{ZnxInfos, ZnxView, ZnxZero}, + layouts::{Data, DataMut, DataRef, ScalarZnx}, }; use sampling::source::Source;@@ -17,6 +17,20 @@ Self {
data: ScalarZnx::alloc(n, 1), dist: Distribution::NONE, } + } +} + +impl<D: DataRef> LWESecret<D> { + pub fn raw(&self) -> &[i64] { + self.data.at(0, 0) + } + + pub fn dist(&self) -> Distribution { + self.dist + } + + pub fn data(&self) -> &ScalarZnx<D> { + &self.data } }
@@ -3,21 +3,24 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GGLWEAutomorphismKey, Infos, prepared::GGLWESwitchingKeyExec}; +use crate::layouts::{ + GGLWEAutomorphismKey, Infos, + prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GGLWEAutomorphismKeyExec<D: Data, B: Backend> { - pub(crate) key: GGLWESwitchingKeyExec<D, B>, +pub struct GGLWEAutomorphismKeyPrepared<D: Data, B: Backend> { + pub(crate) key: GGLWESwitchingKeyPrepared<D, B>, pub(crate) p: i64, } -impl<B: Backend> GGLWEAutomorphismKeyExec<Vec<u8>, B> { +impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self where Module<B>: VmpPMatAlloc<B>, { - GGLWEAutomorphismKeyExec::<Vec<u8>, B> { - key: GGLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank), + GGLWEAutomorphismKeyPrepared::<Vec<u8>, B> { + key: GGLWESwitchingKeyPrepared::alloc(module, n, basek, k, rows, digits, rank, rank), p: 0, } }@@ -26,28 +29,11 @@ pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where Module<B>: VmpPMatAllocBytes, { - GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank) - } - - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank(), - ); - atk_exec.prepare(module, other, scratch); - atk_exec + GGLWESwitchingKeyPrepared::bytes_of(module, n, basek, k, rows, digits, rank, rank) } } -impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -63,7 +49,7 @@ self.key.k()
} } -impl<D: Data, B: Backend> GGLWEAutomorphismKeyExec<D, B> { +impl<D: Data, B: Backend> GGLWEAutomorphismKeyPrepared<D, B> { pub fn p(&self) -> i64 { self.p }@@ -85,13 +71,31 @@ self.key.rank_out()
} } -impl<D: DataMut, B: Backend> GGLWEAutomorphismKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWEAutomorphismKey<DR>> for GGLWEAutomorphismKeyPrepared<D, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DR>, scratch: &mut Scratch<B>) { self.key.prepare(module, &other.key, scratch); self.p = other.p; } -}+} + +impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> for GGLWEAutomorphismKey<D> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> { + let mut atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = GGLWEAutomorphismKeyPrepared::alloc( + module, + self.n(), + self.basek(), + self.k(), + self.rows(), + self.digits(), + self.rank(), + ); + atk_prepared.prepare(module, self, scratch); + atk_prepared + } +}
@@ -3,17 +3,20 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GGLWECiphertext, Infos}; +use crate::layouts::{ + GGLWECiphertext, Infos, + prepared::{Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GGLWECiphertextExec<D: Data, B: Backend> { +pub struct GGLWECiphertextPrepared<D: Data, B: Backend> { pub(crate) data: VmpPMat<D, B>, pub(crate) basek: usize, pub(crate) k: usize, pub(crate) digits: usize, } -impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> { +impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> { pub fn alloc( module: &Module<B>, n: usize,@@ -84,7 +87,7 @@ module.vmp_pmat_alloc_bytes(n, rows, rank_in, rank_out + 1, rows)
} } -impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> { +impl<D: Data, B: Backend> Infos for GGLWECiphertextPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -100,7 +103,7 @@ self.k
} } -impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> { +impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> { pub fn rank(&self) -> usize { self.data.cols_out() - 1 }@@ -118,15 +121,34 @@ self.data.cols_out() - 1
} } -impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWECiphertext<DR>> for GGLWECiphertextPrepared<D, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GGLWECiphertext<DR>, scratch: &mut Scratch<B>) { module.vmp_prepare(&mut self.data, &other.data, scratch); self.basek = other.basek; self.k = other.k; self.digits = other.digits; } } + +impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWECiphertextPrepared<Vec<u8>, B>> for GGLWECiphertext<D> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWECiphertextPrepared<Vec<u8>, B> { + let mut atk_prepared: GGLWECiphertextPrepared<Vec<u8>, B> = GGLWECiphertextPrepared::alloc( + module, + self.n(), + self.basek(), + self.k(), + self.rows(), + self.digits(), + self.rank_in(), + self.rank_out(), + ); + atk_prepared.prepare(module, self, scratch); + atk_prepared + } +}
@@ -3,16 +3,19 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GGLWESwitchingKey, Infos, prepared::GGLWECiphertextExec}; +use crate::layouts::{ + GGLWESwitchingKey, Infos, + prepared::{GGLWECiphertextPrepared, Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GGLWESwitchingKeyExec<D: Data, B: Backend> { - pub(crate) key: GGLWECiphertextExec<D, B>, +pub struct GGLWESwitchingKeyPrepared<D: Data, B: Backend> { + pub(crate) key: GGLWECiphertextPrepared<D, B>, pub(crate) sk_in_n: usize, // Degree of sk_in pub(crate) sk_out_n: usize, // Degree of sk_out } -impl<B: Backend> GGLWESwitchingKeyExec<Vec<u8>, B> { +impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> { pub fn alloc( module: &Module<B>, n: usize,@@ -26,8 +29,8 @@ ) -> Self
where Module<B>: VmpPMatAlloc<B>, { - GGLWESwitchingKeyExec::<Vec<u8>, B> { - key: GGLWECiphertextExec::alloc(module, n, basek, k, rows, digits, rank_in, rank_out), + GGLWESwitchingKeyPrepared::<Vec<u8>, B> { + key: GGLWECiphertextPrepared::alloc(module, n, basek, k, rows, digits, rank_in, rank_out), sk_in_n: 0, sk_out_n: 0, }@@ -46,29 +49,11 @@ ) -> usize
where Module<B>: VmpPMatAllocBytes, { - GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) - } - - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank_in(), - other.rank_out(), - ); - ksk_exec.prepare(module, other, scratch); - ksk_exec + GGLWECiphertextPrepared::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out) } } -impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -84,7 +69,7 @@ self.key.k()
} } -impl<D: Data, B: Backend> GGLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> GGLWESwitchingKeyPrepared<D, B> { pub fn rank(&self) -> usize { self.key.data.cols_out() - 1 }@@ -110,14 +95,33 @@ self.sk_out_n
} } -impl<D: DataMut, B: Backend> GGLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWESwitchingKey<DR>> for GGLWESwitchingKeyPrepared<D, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) { self.key.prepare(module, &other.key, scratch); self.sk_in_n = other.sk_in_n; self.sk_out_n = other.sk_out_n; } } + +impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWESwitchingKeyPrepared<Vec<u8>, B>> for GGLWESwitchingKey<D> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWESwitchingKeyPrepared<Vec<u8>, B> { + let mut atk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = GGLWESwitchingKeyPrepared::alloc( + module, + self.n(), + self.basek(), + self.k(), + self.rows(), + self.digits(), + self.rank_in(), + self.rank_out(), + ); + atk_prepared.prepare(module, self, scratch); + atk_prepared + } +}
@@ -3,22 +3,25 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GGLWETensorKey, Infos, prepared::GGLWESwitchingKeyExec}; +use crate::layouts::{ + GGLWETensorKey, Infos, + prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GGLWETensorKeyExec<D: Data, B: Backend> { - pub(crate) keys: Vec<GGLWESwitchingKeyExec<D, B>>, +pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> { + pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>, } -impl<B: Backend> GGLWETensorKeyExec<Vec<u8>, B> { +impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self where Module<B>: VmpPMatAlloc<B>, { - let mut keys: Vec<GGLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new(); + let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); (0..pairs).for_each(|_| { - keys.push(GGLWESwitchingKeyExec::alloc( + keys.push(GGLWESwitchingKeyPrepared::alloc( module, n, basek, k, rows, digits, 1, rank, )); });@@ -30,32 +33,11 @@ where
Module<B>: VmpPMatAllocBytes, { let pairs: usize = (((rank + 1) * rank) >> 1).max(1); - pairs * GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank) - } - - pub fn from<D: DataRef>( - module: &Module<B>, - other: &GGLWETensorKey<D>, - scratch: &mut Scratch<B>, - ) -> GGLWETensorKeyExec<Vec<u8>, B> - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank(), - ); - tsk_exec.prepare(module, other, scratch); - tsk_exec + pairs * GGLWESwitchingKeyPrepared::bytes_of(module, n, basek, k, rows, digits, 1, rank) } } -impl<D: Data, B: Backend> Infos for GGLWETensorKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for GGLWETensorKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -71,7 +53,7 @@ self.keys[0].k()
} } -impl<D: Data, B: Backend> GGLWETensorKeyExec<D, B> { +impl<D: Data, B: Backend> GGLWETensorKeyPrepared<D, B> { pub fn rank(&self) -> usize { self.keys[0].rank() }@@ -89,9 +71,9 @@ self.keys[0].digits()
} } -impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> { +impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> { // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyExec<D, B> { + pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyPrepared<D, B> { if i > j { std::mem::swap(&mut i, &mut j); };@@ -100,9 +82,9 @@ &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
} } -impl<D: DataRef, B: Backend> GGLWETensorKeyExec<D, B> { +impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> { // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyExec<D, B> { + pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> { if i > j { std::mem::swap(&mut i, &mut j); };@@ -111,12 +93,11 @@ &self.keys[i * rank + j - (i * (i + 1) / 2)]
} } -impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWETensorKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GGLWETensorKey<DR>, scratch: &mut Scratch<B>) { #[cfg(debug_assertions)] { assert_eq!(self.keys.len(), other.keys.len());@@ -129,3 +110,22 @@ a.prepare(module, b, scratch);
}); } } + +impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWETensorKeyPrepared<Vec<u8>, B> { + let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc( + module, + self.n(), + self.basek(), + self.k(), + self.rows(), + self.digits(), + self.rank(), + ); + tsk_prepared.prepare(module, self, scratch); + tsk_prepared + } +}
@@ -3,17 +3,20 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GGSWCiphertext, Infos}; +use crate::layouts::{ + GGSWCiphertext, Infos, + prepared::{Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GGSWCiphertextExec<D: Data, B: Backend> { +pub struct GGSWCiphertextPrepared<D: Data, B: Backend> { pub(crate) data: VmpPMat<D, B>, pub(crate) basek: usize, pub(crate) k: usize, pub(crate) digits: usize, } -impl<B: Backend> GGSWCiphertextExec<Vec<u8>, B> { +impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self where Module<B>: VmpPMatAlloc<B>,@@ -66,30 +69,9 @@ );
module.vmp_pmat_alloc_bytes(n, rows, rank + 1, rank + 1, size) } - - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &GGSWCiphertext<DataOther>, - scratch: &mut Scratch<B>, - ) -> GGSWCiphertextExec<Vec<u8>, B> - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = Self::alloc( - module, - other.n(), - other.basek(), - other.k(), - other.rows(), - other.digits(), - other.rank(), - ); - ggsw_exec.prepare(module, other, scratch); - ggsw_exec - } } -impl<D: Data, B: Backend> Infos for GGSWCiphertextExec<D, B> { +impl<D: Data, B: Backend> Infos for GGSWCiphertextPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -105,7 +87,7 @@ self.k
} } -impl<D: Data, B: Backend> GGSWCiphertextExec<D, B> { +impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> { pub fn rank(&self) -> usize { self.data.cols_out() - 1 }@@ -115,15 +97,39 @@ self.digits
} } -impl<DataSelf: DataMut, B: Backend> GGSWCiphertextExec<DataSelf, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGSWCiphertext<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<D: DataRef, B: Backend> GGSWCiphertextPrepared<D, B> { + pub fn data(&self) -> &VmpPMat<D, B> { + &self.data + } +} + +impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGSWCiphertext<DR>> for GGSWCiphertextPrepared<D, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GGSWCiphertext<DR>, scratch: &mut Scratch<B>) { module.vmp_prepare(&mut self.data, &other.data, scratch); self.k = other.k; self.basek = other.basek; self.digits = other.digits; } } + +impl<D: DataRef, B: Backend> PrepareAlloc<B, GGSWCiphertextPrepared<Vec<u8>, B>> for GGSWCiphertext<D> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGSWCiphertextPrepared<Vec<u8>, B> { + let mut ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = GGSWCiphertextPrepared::alloc( + module, + self.n(), + self.basek(), + self.k(), + self.rows(), + self.digits(), + self.rank(), + ); + ggsw_prepared.prepare(module, self, scratch); + ggsw_prepared + } +}
@@ -5,18 +5,21 @@ };
use crate::{ dist::Distribution, - layouts::{GLWEPublicKey, Infos}, + layouts::{ + GLWEPublicKey, Infos, + prepared::{Prepare, PrepareAlloc}, + }, }; #[derive(PartialEq, Eq)] -pub struct GLWEPublicKeyExec<D: Data, B: Backend> { +pub struct GLWEPublicKeyPrepared<D: Data, B: Backend> { pub(crate) data: VecZnxDft<D, B>, pub(crate) basek: usize, pub(crate) k: usize, pub(crate) dist: Distribution, } -impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for GLWEPublicKeyPrepared<D, B> { type Inner = VecZnxDft<D, B>; fn inner(&self) -> &Self::Inner {@@ -32,13 +35,13 @@ self.k
} } -impl<D: Data, B: Backend> GLWEPublicKeyExec<D, B> { +impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> { pub fn rank(&self) -> usize { self.cols() - 1 } } -impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> { +impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> Self where Module<B>: VecZnxDftAlloc<B>,@@ -57,25 +60,25 @@ Module<B>: VecZnxDftAllocBytes,
{ module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek)) } +} - pub fn from<DataOther>(module: &Module<B>, other: &GLWEPublicKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - DataOther: DataRef, - Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>, - { - let mut pk_exec: GLWEPublicKeyExec<Vec<u8>, B> = - GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank()); - pk_exec.prepare(module, other, scratch); - pk_exec +impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEPublicKeyPrepared<Vec<u8>, B>> for GLWEPublicKey<D> +where + Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEPublicKeyPrepared<Vec<u8>, B> { + let mut pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = + GLWEPublicKeyPrepared::alloc(module, self.n(), self.basek(), self.k(), self.rank()); + pk_prepared.prepare(module, self, scratch); + pk_prepared } } -impl<D: DataMut, B: Backend> GLWEPublicKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEPublicKey<DataOther>, _scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VecZnxDftFromVecZnx<B>, - { +impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEPublicKey<DR>> for GLWEPublicKeyPrepared<DM, B> +where + Module<B>: VecZnxDftFromVecZnx<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GLWEPublicKey<DR>, _scratch: &mut Scratch<B>) { #[cfg(debug_assertions)] { assert_eq!(self.n(), other.n());
@@ -3,17 +3,24 @@ api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, ZnxInfos},
layouts::{Backend, Data, DataMut, DataRef, Module, SvpPPol}, }; -use crate::{dist::Distribution, layouts::GLWESecret, trait_families::GLWESecretExecModuleFamily}; +use crate::{ + dist::Distribution, + layouts::{ + GLWESecret, + prepared::{Prepare, PrepareAlloc}, + }, + trait_families::GLWESecretPreparedModuleFamily, +}; -pub struct GLWESecretExec<D: Data, B: Backend> { +pub struct GLWESecretPrepared<D: Data, B: Backend> { pub(crate) data: SvpPPol<D, B>, pub(crate) dist: Distribution, } -impl<B: Backend> GLWESecretExec<Vec<u8>, B> { +impl<B: Backend> GLWESecretPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, rank: usize) -> Self where - Module<B>: GLWESecretExecModuleFamily<B>, + Module<B>: GLWESecretPreparedModuleFamily<B>, { Self { data: module.svp_ppol_alloc(n, rank),@@ -23,25 +30,13 @@ }
pub fn bytes_of(module: &Module<B>, n: usize, rank: usize) -> usize where - Module<B>: GLWESecretExecModuleFamily<B>, + Module<B>: GLWESecretPreparedModuleFamily<B>, { module.svp_ppol_alloc_bytes(n, rank) } } -impl<B: Backend> GLWESecretExec<Vec<u8>, B> { - pub fn from<D>(module: &Module<B>, sk: &GLWESecret<D>) -> Self - where - D: DataRef, - Module<B>: GLWESecretExecModuleFamily<B>, - { - let mut sk_dft: GLWESecretExec<Vec<u8>, B> = Self::alloc(module, sk.n(), sk.rank()); - sk_dft.prepare(module, sk); - sk_dft - } -} - -impl<D: Data, B: Backend> GLWESecretExec<D, B> { +impl<D: Data, B: Backend> GLWESecretPrepared<D, B> { pub fn n(&self) -> usize { self.data.n() }@@ -55,15 +50,29 @@ self.data.cols()
} } -impl<D: DataMut, B: Backend> GLWESecretExec<D, B> { - pub(crate) fn prepare<O>(&mut self, module: &Module<B>, sk: &GLWESecret<O>) - where - O: DataRef, - Module<B>: GLWESecretExecModuleFamily<B>, - { +impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWESecretPrepared<Vec<u8>, B>> for GLWESecret<D> +where + Module<B>: SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>, +{ + fn prepare_alloc( + &self, + module: &Module<B>, + scratch: &mut backend::hal::layouts::Scratch<B>, + ) -> GLWESecretPrepared<Vec<u8>, B> { + let mut sk_dft: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, self.n(), self.rank()); + sk_dft.prepare(module, self, scratch); + sk_dft + } +} + +impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWESecret<DR>> for GLWESecretPrepared<DM, B> +where + Module<B>: SvpPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GLWESecret<DR>, _scratch: &mut backend::hal::layouts::Scratch<B>) { (0..self.rank()).for_each(|i| { - module.svp_prepare(&mut self.data, i, &sk.data, i); + module.svp_prepare(&mut self.data, i, &other.data, i); }); - self.dist = sk.dist + self.dist = other.dist } }
@@ -3,12 +3,15 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{GLWEToLWESwitchingKey, Infos, prepared::GGLWESwitchingKeyExec}; +use crate::layouts::{ + GLWEToLWESwitchingKey, Infos, + prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct GLWEToLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); +pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); -impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -24,7 +27,7 @@ self.0.k()
} } -impl<D: Data, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> GLWEToLWESwitchingKeyPrepared<D, B> { pub fn digits(&self) -> usize { self.0.digits() }@@ -42,12 +45,12 @@ self.0.rank_out()
} } -impl<B: Backend> GLWEToLWESwitchingKeyExec<Vec<u8>, B> { +impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self where Module<B>: VmpPMatAlloc<B>, { - Self(GGLWESwitchingKeyExec::alloc( + Self(GGLWESwitchingKeyPrepared::alloc( module, n, basek, k, rows, 1, rank_in, 1, )) }@@ -56,36 +59,33 @@ pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize
where Module<B>: VmpPMatAllocBytes, { - GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) + GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1) } +} - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &GLWEToLWESwitchingKey<DataOther>, - scratch: &mut Scratch<B>, - ) -> Self - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( +impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWESwitchingKey<D> +where + Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { + let mut ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = GLWEToLWESwitchingKeyPrepared::alloc( module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), - other.0.rank_in(), + self.0.n(), + self.0.basek(), + self.0.k(), + self.0.rows(), + self.0.rank_in(), ); - ksk_exec.prepare(module, other, scratch); - ksk_exec + ksk_prepared.prepare(module, self, scratch); + ksk_prepared } } -impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWESwitchingKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DR>, scratch: &mut Scratch<B>) { self.0.prepare(module, &other.0, scratch); } }
@@ -3,12 +3,15 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{Infos, LWESwitchingKey, prepared::GGLWESwitchingKeyExec}; +use crate::layouts::{ + Infos, LWESwitchingKey, + prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, +}; #[derive(PartialEq, Eq)] -pub struct LWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); +pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); -impl<D: Data, B: Backend> Infos for LWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for LWESwitchingKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -24,7 +27,7 @@ self.0.k()
} } -impl<D: Data, B: Backend> LWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> LWESwitchingKeyPrepared<D, B> { pub fn digits(&self) -> usize { self.0.digits() }@@ -42,12 +45,12 @@ self.0.rank_out()
} } -impl<B: Backend> LWESwitchingKeyExec<Vec<u8>, B> { +impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize) -> Self where Module<B>: VmpPMatAlloc<B>, { - Self(GGLWESwitchingKeyExec::alloc( + Self(GGLWESwitchingKeyPrepared::alloc( module, n, basek, k, rows, 1, 1, 1, )) }@@ -56,31 +59,32 @@ pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize) -> usize
where Module<B>: VmpPMatAllocBytes, { - GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) + GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1) } +} - pub fn from<DataOther: DataRef>(module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( +impl<D: DataRef, B: Backend> PrepareAlloc<B, LWESwitchingKeyPrepared<Vec<u8>, B>> for LWESwitchingKey<D> +where + Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWESwitchingKeyPrepared<Vec<u8>, B> { + let mut ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = LWESwitchingKeyPrepared::alloc( module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), + self.0.n(), + self.0.basek(), + self.0.k(), + self.0.rows(), ); - ksk_exec.prepare(module, other, scratch); - ksk_exec + ksk_prepared.prepare(module, self, scratch); + ksk_prepared } } -impl<D: DataMut, B: Backend> LWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWESwitchingKey<DR>> for LWESwitchingKeyPrepared<DM, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &LWESwitchingKey<DR>, scratch: &mut Scratch<B>) { self.0.prepare(module, &other.0, scratch); } }
@@ -3,13 +3,16 @@ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; -use crate::layouts::{Infos, LWEToGLWESwitchingKey, prepared::GGLWESwitchingKeyExec}; +use crate::layouts::{ + Infos, LWEToGLWESwitchingKey, + prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, +}; /// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext]. #[derive(PartialEq, Eq)] -pub struct LWEToGLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>); +pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); -impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyPrepared<D, B> { type Inner = VmpPMat<D, B>; fn inner(&self) -> &Self::Inner {@@ -25,7 +28,7 @@ self.0.k()
} } -impl<D: Data, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { +impl<D: Data, B: Backend> LWEToGLWESwitchingKeyPrepared<D, B> { pub fn digits(&self) -> usize { self.0.digits() }@@ -43,12 +46,12 @@ self.0.rank_out()
} } -impl<B: Backend> LWEToGLWESwitchingKeyExec<Vec<u8>, B> { +impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self where Module<B>: VmpPMatAlloc<B>, { - Self(GGLWESwitchingKeyExec::alloc( + Self(GGLWESwitchingKeyPrepared::alloc( module, n, basek, k, rows, 1, 1, rank_out, )) }@@ -57,36 +60,33 @@ pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_out: usize) -> usize
where Module<B>: VmpPMatAllocBytes, { - GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) + GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out) } +} - pub fn from<DataOther: DataRef>( - module: &Module<B>, - other: &LWEToGLWESwitchingKey<DataOther>, - scratch: &mut Scratch<B>, - ) -> Self - where - Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, - { - let mut ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc( +impl<D: DataRef, B: Backend> PrepareAlloc<B, LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>> for LWEToGLWESwitchingKey<D> +where + Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { + let mut ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = LWEToGLWESwitchingKeyPrepared::alloc( module, - other.0.n(), - other.0.basek(), - other.0.k(), - other.0.rows(), - other.0.rank(), + self.0.n(), + self.0.basek(), + self.0.k(), + self.0.rows(), + self.0.rank_out(), ); - ksk_exec.prepare(module, other, scratch); - ksk_exec + ksk_prepared.prepare(module, self, scratch); + ksk_prepared } } -impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyExec<D, B> { - pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) - where - DataOther: DataRef, - Module<B>: VmpPMatPrepare<B>, - { +impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWEToGLWESwitchingKey<DR>> for LWEToGLWESwitchingKeyPrepared<DM, B> +where + Module<B>: VmpPMatPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) { self.0.prepare(module, &other.0, scratch); } }
@@ -9,6 +9,7 @@ mod glwe_to_lwe_ksk;
mod lwe_ksk; mod lwe_to_glwe_ksk; +use backend::hal::layouts::{Backend, Module, Scratch}; pub use gglwe_atk::*; pub use gglwe_ct::*; pub use gglwe_ksk::*;@@ -19,3 +20,11 @@ pub use glwe_sk::*;
pub use glwe_to_lwe_ksk::*; pub use lwe_ksk::*; pub use lwe_to_glwe_ksk::*; + +pub trait PrepareAlloc<B: Backend, T> { + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> T; +} + +pub trait Prepare<B: Backend, T> { + fn prepare(&mut self, module: &Module<B>, other: &T, scratch: &mut Scratch<B>); +}
@@ -11,10 +11,12 @@ mod keyswitching;
mod noise; mod operations; mod scratch; +mod utils; pub use operations::*; pub mod layouts; pub mod trait_families; +pub use dist::*; pub use glwe_packing::*; pub use scratch::*;
@@ -1,11 +1,11 @@
use backend::hal::{ - api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxStd, VecZnxSubScalarInplace, ZnxZero}, + api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxSubScalarInplace, ZnxZero}, layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; use crate::{ - layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + layouts::{GGLWECiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretPrepared}, trait_families::GLWEDecryptFamily, };@@ -13,13 +13,13 @@ impl<D: DataRef> GGLWECiphertext<D> {
pub fn assert_noise<B: Backend, DataSk, DataWant>( self, module: &Module<B>, - sk: &GLWESecretExec<DataSk, B>, + sk: &GLWESecretPrepared<DataSk, B>, pt_want: &ScalarZnx<DataWant>, max_noise: f64, ) where DataSk: DataRef, DataWant: DataRef, - Module<B>: GLWEDecryptFamily<B> + VecZnxStd + VecZnxSubScalarInplace, + Module<B>: GLWEDecryptFamily<B> + VecZnxSubScalarInplace, B: TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let digits: usize = self.digits();@@ -47,7 +47,7 @@ pt_want,
col_i, ); - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_have: f64 = pt.data.std(basek, 0).log2(); assert!( noise_have <= max_noise,
@@ -1,14 +1,14 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxDftAlloc, - VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeTmpBytes, VecZnxStd, VecZnxSubABInplace, ZnxZero, + VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeTmpBytes, VecZnxSubABInplace, ZnxZero, }, layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, VecZnxBig, VecZnxDft}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; use crate::{ - layouts::{GGSWCiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretExec}, + layouts::{GGSWCiphertext, GLWECiphertext, GLWEPlaintext, Infos, prepared::GLWESecretPrepared}, trait_families::GGSWAssertNoiseFamily, };@@ -16,13 +16,13 @@ impl<D: DataRef> GGSWCiphertext<D> {
pub fn assert_noise<B: Backend, DataSk, DataScalar, F>( &self, module: &Module<B>, - sk_exec: &GLWESecretExec<DataSk, B>, + sk_prepared: &GLWESecretPrepared<DataSk, B>, pt_want: &ScalarZnx<DataScalar>, max_noise: F, ) where DataSk: DataRef, DataScalar: DataRef, - Module<B>: GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace + VecZnxStd, + Module<B>: GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace, B: TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, F: Fn(usize) -> f64, {@@ -46,17 +46,17 @@
// mul with sk[col_j-1] if col_j > 0 { module.vec_znx_dft_from_vec_znx(1, 0, &mut pt_dft, 0, &pt.data, 0); - module.svp_apply_inplace(&mut pt_dft, 0, &sk_exec.data, col_j - 1); + module.svp_apply_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut pt_big, 0, &mut pt_dft, 0); module.vec_znx_big_normalize(basek, &mut pt.data, 0, &pt_big, 0, scratch.borrow()); } self.at(row_i, col_j) - .decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + .decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); module.vec_znx_sub_ab_inplace(&mut pt_have.data, 0, &pt.data, 0); - let std_pt: f64 = module.vec_znx_std(basek, &pt_have.data, 0).log2(); + let std_pt: f64 = pt_have.data.std(basek, 0).log2(); let noise: f64 = max_noise(col_j); println!("{} {}", std_pt, noise); assert!(std_pt <= noise, "{} > {}", std_pt, noise);@@ -71,12 +71,12 @@ impl<D: DataRef> GGSWCiphertext<D> {
pub fn print_noise<B: Backend, DataSk, DataScalar>( &self, module: &Module<B>, - sk_exec: &GLWESecretExec<DataSk, B>, + sk_prepared: &GLWESecretPrepared<DataSk, B>, pt_want: &ScalarZnx<DataScalar>, ) where DataSk: DataRef, DataScalar: DataRef, - Module<B>: GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace + VecZnxStd, + Module<B>: GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace, B: TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let basek: usize = self.basek();@@ -99,17 +99,17 @@
// mul with sk[col_j-1] if col_j > 0 { module.vec_znx_dft_from_vec_znx(1, 0, &mut pt_dft, 0, &pt.data, 0); - module.svp_apply_inplace(&mut pt_dft, 0, &sk_exec.data, col_j - 1); + module.svp_apply_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut pt_big, 0, &mut pt_dft, 0); module.vec_znx_big_normalize(basek, &mut pt.data, 0, &pt_big, 0, scratch.borrow()); } self.at(row_i, col_j) - .decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + .decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); module.vec_znx_sub_ab_inplace(&mut pt_have.data, 0, &pt.data, 0); - let std_pt: f64 = module.vec_znx_std(basek, &pt_have.data, 0).log2(); + let std_pt: f64 = pt_have.data.std(basek, 0).log2(); println!("{}", std_pt); pt.data.zero(); });
@@ -1,12 +1,12 @@
use backend::hal::{ - api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalizeInplace, VecZnxStd, VecZnxSubABInplace}, + api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalizeInplace, VecZnxSubABInplace}, layouts::{Backend, DataRef, Module, ScratchOwned}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, }; use crate::{ layouts::GLWEPlaintext, - layouts::prepared::GLWESecretExec, + layouts::prepared::GLWESecretPrepared, layouts::{GLWECiphertext, Infos}, trait_families::GLWEDecryptFamily, };@@ -15,13 +15,13 @@ impl<D: DataRef> GLWECiphertext<D> {
pub fn assert_noise<B: Backend, DataSk, DataPt>( &self, module: &Module<B>, - sk_exec: &GLWESecretExec<DataSk, B>, + sk_prepared: &GLWESecretPrepared<DataSk, B>, pt_want: &GLWEPlaintext<DataPt>, max_noise: f64, ) where DataSk: DataRef, DataPt: DataRef, - Module<B>: GLWEDecryptFamily<B> + VecZnxSubABInplace + VecZnxNormalizeInplace<B> + VecZnxStd, + Module<B>: GLWEDecryptFamily<B> + VecZnxSubABInplace + VecZnxNormalizeInplace<B>, B: TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self.n(), self.basek(), self.k());@@ -33,12 +33,12 @@ self.basek(),
self.k(), )); - self.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + self.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); module.vec_znx_sub_ab_inplace(&mut pt_have.data, 0, &pt_want.data, 0); module.vec_znx_normalize_inplace(self.basek(), &mut pt_have.data, 0, scratch.borrow()); - let noise_have: f64 = module.vec_znx_std(self.basek(), &pt_have.data, 0).log2(); + let noise_have: f64 = pt_have.data.std(self.basek(), 0).log2(); assert!(noise_have <= max_noise, "{} {}", noise_have, max_noise); } }
@@ -7,11 +7,11 @@
use crate::{ dist::Distribution, layouts::{ - GGLWEAutomorphismKey, GGLWECiphertext, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWEPublicKey, - GLWESecret, GGLWESwitchingKey, Infos, + GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GLWEPlaintext, + GLWEPublicKey, GLWESecret, Infos, prepared::{ - GGLWEAutomorphismKeyExec, GGLWECiphertextExec, GGSWCiphertextExec, GLWEPublicKeyExec, GLWESecretExec, - GGLWESwitchingKeyExec, GGLWETensorKeyExec, + GGLWEAutomorphismKeyPrepared, GGLWECiphertextPrepared, GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared, + GGSWCiphertextPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared, }, }, };@@ -53,8 +53,8 @@ rank_out: usize,
) -> (GGLWECiphertext<&mut [u8]>, &mut Self); } -pub trait TakeGGLWEExec<B: Backend> { - fn take_gglwe_exec( +pub trait TakeGGLWEPrepared<B: Backend> { + fn take_gglwe_prepared( &mut self, n: usize, basek: usize,@@ -63,7 +63,7 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GGLWECiphertextExec<&mut [u8], B>, &mut Self); + ) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self); } pub trait TakeGGSW<B: Backend> {@@ -78,8 +78,8 @@ rank: usize,
) -> (GGSWCiphertext<&mut [u8]>, &mut Self); } -pub trait TakeGGSWExec<B: Backend> { - fn take_ggsw_exec( +pub trait TakeGGSWPrepared<B: Backend> { + fn take_ggsw_prepared( &mut self, n: usize, basek: usize,@@ -87,29 +87,29 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGSWCiphertextExec<&mut [u8], B>, &mut Self); + ) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self); } pub trait TakeGLWESecret<B: Backend> { fn take_glwe_secret(&mut self, n: usize, rank: usize) -> (GLWESecret<&mut [u8]>, &mut Self); } -pub trait TakeGLWESecretExec<B: Backend> { - fn take_glwe_secret_exec(&mut self, n: usize, rank: usize) -> (GLWESecretExec<&mut [u8], B>, &mut Self); +pub trait TakeGLWESecretPrepared<B: Backend> { + fn take_glwe_secret_prepared(&mut self, n: usize, rank: usize) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self); } pub trait TakeGLWEPk<B: Backend> { fn take_glwe_pk(&mut self, n: usize, basek: usize, k: usize, rank: usize) -> (GLWEPublicKey<&mut [u8]>, &mut Self); } -pub trait TakeGLWEPkExec<B: Backend> { - fn take_glwe_pk_exec( +pub trait TakeGLWEPkPrepared<B: Backend> { + fn take_glwe_pk_prepared( &mut self, n: usize, basek: usize, k: usize, rank: usize, - ) -> (GLWEPublicKeyExec<&mut [u8], B>, &mut Self); + ) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self); } pub trait TakeGLWESwitchingKey<B: Backend> {@@ -125,8 +125,8 @@ rank_out: usize,
) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self); } -pub trait TakeGLWESwitchingKeyExec<B: Backend> { - fn take_glwe_switching_key_exec( +pub trait TakeGLWESwitchingKeyPrepared<B: Backend> { + fn take_glwe_switching_key_prepared( &mut self, n: usize, basek: usize,@@ -135,7 +135,7 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GGLWESwitchingKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self); } pub trait TakeTensorKey<B: Backend> {@@ -150,8 +150,8 @@ rank: usize,
) -> (GGLWETensorKey<&mut [u8]>, &mut Self); } -pub trait TakeTensorKeyExec<B: Backend> { - fn take_tensor_key_exec( +pub trait TakeTensorKeyPrepared<B: Backend> { + fn take_tensor_key_prepared( &mut self, n: usize, basek: usize,@@ -159,7 +159,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self); } pub trait TakeAutomorphismKey<B: Backend> {@@ -174,8 +174,8 @@ rank: usize,
) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self); } -pub trait TakeAutomorphismKeyExec<B: Backend> { - fn take_automorphism_key_exec( +pub trait TakeAutomorphismKeyPrepared<B: Backend> { + fn take_automorphism_key_prepared( &mut self, n: usize, basek: usize,@@ -183,7 +183,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGLWEAutomorphismKeyExec<&mut [u8], B>, &mut Self); + ) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self); } impl<B: Backend> TakeGLWECt<B> for Scratch<B>@@ -330,11 +330,11 @@ )
} } -impl<B: Backend> TakeGGLWEExec<B> for Scratch<B> +impl<B: Backend> TakeGGLWEPrepared<B> for Scratch<B> where Scratch<B>: TakeVmpPMat<B>, { - fn take_gglwe_exec( + fn take_gglwe_prepared( &mut self, n: usize, basek: usize,@@ -343,7 +343,7 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GGLWECiphertextExec<&mut [u8], B>, &mut Self) { + ) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vmp_pmat( n, rows.div_ceil(digits),@@ -352,7 +352,7 @@ rank_out + 1,
k.div_ceil(basek), ); ( - GGLWECiphertextExec { + GGLWECiphertextPrepared { data: data, basek: basek, k,@@ -363,14 +363,14 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GGLWECiphertextExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWECiphertextPrepared<D, B>> for Scratch<B> where B: Backend + TakeVmpPMatImpl<B>, D: DataRef, { - type Output = GGLWECiphertextExec<&'a mut [u8], B>; + type Output = GGLWECiphertextPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GGLWECiphertextExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWECiphertextPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vmp_pmat_impl( self, template.n(),@@ -380,7 +380,7 @@ template.data.cols_out(),
template.size(), ); ( - GGLWECiphertextExec { + GGLWECiphertextPrepared { data, basek: template.basek(), k: template.k(),@@ -451,11 +451,11 @@ )
} } -impl<B: Backend> TakeGGSWExec<B> for Scratch<B> +impl<B: Backend> TakeGGSWPrepared<B> for Scratch<B> where Scratch<B>: TakeVmpPMat<B>, { - fn take_ggsw_exec( + fn take_ggsw_prepared( &mut self, n: usize, basek: usize,@@ -463,7 +463,7 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGSWCiphertextExec<&mut [u8], B>, &mut Self) { + ) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vmp_pmat( n, rows.div_ceil(digits),@@ -472,7 +472,7 @@ rank + 1,
k.div_ceil(basek), ); ( - GGSWCiphertextExec { + GGSWCiphertextPrepared { data, basek, k,@@ -483,14 +483,14 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GGSWCiphertextExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGSWCiphertextPrepared<D, B>> for Scratch<B> where B: Backend + TakeVmpPMatImpl<B>, D: DataRef, { - type Output = GGSWCiphertextExec<&'a mut [u8], B>; + type Output = GGSWCiphertextPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GGSWCiphertextExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGSWCiphertextPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vmp_pmat_impl( self, template.n(),@@ -500,7 +500,7 @@ template.data.cols_out(),
template.size(), ); ( - GGSWCiphertextExec { + GGSWCiphertextPrepared { data, basek: template.basek(), k: template.k(),@@ -550,20 +550,20 @@ )
} } -impl<B: Backend> TakeGLWEPkExec<B> for Scratch<B> +impl<B: Backend> TakeGLWEPkPrepared<B> for Scratch<B> where Scratch<B>: TakeVecZnxDft<B>, { - fn take_glwe_pk_exec( + fn take_glwe_pk_prepared( &mut self, n: usize, basek: usize, k: usize, rank: usize, - ) -> (GLWEPublicKeyExec<&mut [u8], B>, &mut Self) { + ) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_vec_znx_dft(n, rank + 1, k.div_ceil(basek)); ( - GLWEPublicKeyExec { + GLWEPublicKeyPrepared { data, k, basek,@@ -574,17 +574,17 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GLWEPublicKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GLWEPublicKeyPrepared<D, B>> for Scratch<B> where B: Backend + TakeVecZnxDftImpl<B>, D: DataRef, { - type Output = GLWEPublicKeyExec<&'a mut [u8], B>; + type Output = GLWEPublicKeyPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWEPublicKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GLWEPublicKeyPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_vec_znx_dft_impl(self, template.n(), template.cols(), template.size()); ( - GLWEPublicKeyExec { + GLWEPublicKeyPrepared { data, basek: template.basek(), k: template.k(),@@ -630,14 +630,14 @@ )
} } -impl<B: Backend> TakeGLWESecretExec<B> for Scratch<B> +impl<B: Backend> TakeGLWESecretPrepared<B> for Scratch<B> where Scratch<B>: TakeSvpPPol<B>, { - fn take_glwe_secret_exec(&mut self, n: usize, rank: usize) -> (GLWESecretExec<&mut [u8], B>, &mut Self) { + fn take_glwe_secret_prepared(&mut self, n: usize, rank: usize) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self) { let (data, scratch) = self.take_svp_ppol(n, rank); ( - GLWESecretExec { + GLWESecretPrepared { data, dist: Distribution::NONE, },@@ -646,17 +646,17 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GLWESecretExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GLWESecretPrepared<D, B>> for Scratch<B> where B: Backend + TakeSvpPPolImpl<B>, D: DataRef, { - type Output = GLWESecretExec<&'a mut [u8], B>; + type Output = GLWESecretPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GLWESecretExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GLWESecretPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (data, scratch) = B::take_svp_ppol_impl(self, template.n(), template.rank()); ( - GLWESecretExec { + GLWESecretPrepared { data, dist: template.dist, },@@ -712,11 +712,11 @@ )
} } -impl<B: Backend> TakeGLWESwitchingKeyExec<B> for Scratch<B> +impl<B: Backend> TakeGLWESwitchingKeyPrepared<B> for Scratch<B> where - Scratch<B>: TakeGGLWEExec<B>, + Scratch<B>: TakeGGLWEPrepared<B>, { - fn take_glwe_switching_key_exec( + fn take_glwe_switching_key_prepared( &mut self, n: usize, basek: usize,@@ -725,10 +725,10 @@ rows: usize,
digits: usize, rank_in: usize, rank_out: usize, - ) -> (GGLWESwitchingKeyExec<&mut [u8], B>, &mut Self) { - let (data, scratch) = self.take_gglwe_exec(n, basek, k, rows, digits, rank_in, rank_out); + ) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) { + let (data, scratch) = self.take_gglwe_prepared(n, basek, k, rows, digits, rank_in, rank_out); ( - GGLWESwitchingKeyExec { + GGLWESwitchingKeyPrepared { key: data, sk_in_n: 0, sk_out_n: 0,@@ -738,18 +738,18 @@ )
} } -impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWESwitchingKeyPrepared<D, B>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GGLWECiphertextExec<D, B>, Output = GGLWECiphertextExec<&'a mut [u8], B>>, + Scratch<B>: TakeLike<'a, B, GGLWECiphertextPrepared<D, B>, Output = GGLWECiphertextPrepared<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GGLWESwitchingKeyExec<&'a mut [u8], B>; + type Output = GGLWESwitchingKeyPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GGLWESwitchingKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWESwitchingKeyPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); ( - GGLWESwitchingKeyExec { + GGLWESwitchingKeyPrepared { key, sk_in_n: template.sk_in_n, sk_out_n: template.sk_out_n,@@ -791,11 +791,11 @@ (GGLWEAutomorphismKey { key, p: template.p }, scratch)
} } -impl<B: Backend> TakeAutomorphismKeyExec<B> for Scratch<B> +impl<B: Backend> TakeAutomorphismKeyPrepared<B> for Scratch<B> where - Scratch<B>: TakeGLWESwitchingKeyExec<B>, + Scratch<B>: TakeGLWESwitchingKeyPrepared<B>, { - fn take_automorphism_key_exec( + fn take_automorphism_key_prepared( &mut self, n: usize, basek: usize,@@ -803,23 +803,23 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGLWEAutomorphismKeyExec<&mut [u8], B>, &mut Self) { - let (data, scratch) = self.take_glwe_switching_key_exec(n, basek, k, rows, digits, rank, rank); - (GGLWEAutomorphismKeyExec { key: data, p: 0 }, scratch) + ) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self) { + let (data, scratch) = self.take_glwe_switching_key_prepared(n, basek, k, rows, digits, rank, rank); + (GGLWEAutomorphismKeyPrepared { key: data, p: 0 }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWEAutomorphismKeyPrepared<D, B>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyPrepared<D, B>, Output = GGLWESwitchingKeyPrepared<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GGLWEAutomorphismKeyExec<&'a mut [u8], B>; + type Output = GGLWEAutomorphismKeyPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GGLWEAutomorphismKeyExec<D, B>) -> (Self::Output, &'a mut Self) { + fn take_like(&'a mut self, template: &GGLWEAutomorphismKeyPrepared<D, B>) -> (Self::Output, &'a mut Self) { let (key, scratch) = self.take_like(&template.key); - (GGLWEAutomorphismKeyExec { key, p: template.p }, scratch) + (GGLWEAutomorphismKeyPrepared { key, p: template.p }, scratch) } }@@ -884,11 +884,11 @@ (GGLWETensorKey { keys }, scratch)
} } -impl<B: Backend> TakeTensorKeyExec<B> for Scratch<B> +impl<B: Backend> TakeTensorKeyPrepared<B> for Scratch<B> where Scratch<B>: TakeVmpPMat<B>, { - fn take_tensor_key_exec( + fn take_tensor_key_prepared( &mut self, n: usize, basek: usize,@@ -896,36 +896,36 @@ k: usize,
rows: usize, digits: usize, rank: usize, - ) -> (GGLWETensorKeyExec<&mut [u8], B>, &mut Self) { - let mut keys: Vec<GGLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); + ) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self) { + let mut keys: Vec<GGLWESwitchingKeyPrepared<&mut [u8], B>> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); let mut scratch: &mut Scratch<B> = self; if pairs != 0 { - let (gglwe, s) = scratch.take_glwe_switching_key_exec(n, basek, k, rows, digits, 1, rank); + let (gglwe, s) = scratch.take_glwe_switching_key_prepared(n, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } for _ in 1..pairs { - let (gglwe, s) = scratch.take_glwe_switching_key_exec(n, basek, k, rows, digits, 1, rank); + let (gglwe, s) = scratch.take_glwe_switching_key_prepared(n, basek, k, rows, digits, 1, rank); scratch = s; keys.push(gglwe); } - (GGLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyPrepared { keys }, scratch) } } -impl<'a, B, D> TakeLike<'a, B, GGLWETensorKeyExec<D, B>> for Scratch<B> +impl<'a, B, D> TakeLike<'a, B, GGLWETensorKeyPrepared<D, B>> for Scratch<B> where - Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyExec<D, B>, Output = GGLWESwitchingKeyExec<&'a mut [u8], B>>, + Scratch<B>: TakeLike<'a, B, GGLWESwitchingKeyPrepared<D, B>, Output = GGLWESwitchingKeyPrepared<&'a mut [u8], B>>, B: Backend + TakeMatZnxImpl<B>, D: DataRef, { - type Output = GGLWETensorKeyExec<&'a mut [u8], B>; + type Output = GGLWETensorKeyPrepared<&'a mut [u8], B>; - fn take_like(&'a mut self, template: &GGLWETensorKeyExec<D, B>) -> (Self::Output, &'a mut Self) { - let mut keys: Vec<GGLWESwitchingKeyExec<&mut [u8], B>> = Vec::new(); + fn take_like(&'a mut self, template: &GGLWETensorKeyPrepared<D, B>) -> (Self::Output, &'a mut Self) { + let mut keys: Vec<GGLWESwitchingKeyPrepared<&mut [u8], B>> = Vec::new(); let pairs: usize = template.keys.len(); let mut scratch: &mut Scratch<B> = self;@@ -941,6 +941,6 @@ scratch = s;
keys.push(gglwe); } - (GGLWETensorKeyExec { keys }, scratch) + (GGLWETensorKeyPrepared { keys }, scratch) } }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -14,13 +14,13 @@
use crate::{ layouts::{ GGLWEAutomorphismKey, GLWEPlaintext, GLWESecret, Infos, - prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_gglwe_automorphism_key_automorphism<B: Backend>( module: &Module<B>,@@ -35,7 +35,7 @@ sigma: f64,
rank: usize, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree@@ -44,7 +44,6 @@ + VecZnxAutomorphism
+ VecZnxAutomorphismInplace + GLWEDecryptFamily<B> + VecZnxSubScalarInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -102,13 +101,18 @@ sigma,
scratch.borrow(), ); - let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); + auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key_out.automorphism(module, &auto_key_in, &auto_key_apply_exec, scratch.borrow()); + auto_key_out.automorphism( + module, + &auto_key_in, + &auto_key_apply_prepared, + scratch.borrow(), + ); let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_out);@@ -124,7 +128,7 @@ i,
); }); - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); + let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow()); (0..auto_key_out.rank_in()).for_each(|col_i| { (0..auto_key_out.rows()).for_each(|row_i| {@@ -140,7 +144,7 @@ &sk.data,
col_i, ); - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_have: f64 = pt.data.std(basek, 0).log2(); let noise_want: f64 = log2_std_noise_gglwe_product( n as f64, basek * digits,@@ -176,7 +180,7 @@ sigma: f64,
rank: usize, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree@@ -185,7 +189,6 @@ + VecZnxAutomorphism
+ VecZnxAutomorphismInplace + GLWEDecryptFamily<B> + VecZnxSubScalarInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -242,13 +245,13 @@ sigma,
scratch.borrow(), ); - let mut auto_key_apply_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank); + let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_apply, rows_apply, digits, rank); - auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow()); + auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - auto_key.automorphism_inplace(module, &auto_key_apply_exec, scratch.borrow()); + auto_key.automorphism_inplace(module, &auto_key_apply_prepared, scratch.borrow()); let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);@@ -265,7 +268,7 @@ i,
); }); - let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto); + let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow()); (0..auto_key.rank_in()).for_each(|col_i| { (0..auto_key.rows()).for_each(|row_i| {@@ -280,7 +283,7 @@ &sk.data,
col_i, ); - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_have: f64 = pt.data.std(basek, 0).log2(); let noise_want: f64 = log2_std_noise_gglwe_product( n as f64, basek * digits,
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{@@ -14,14 +14,14 @@
use crate::{ layouts::{ GGLWEAutomorphismKey, GGLWETensorKey, GGSWCiphertext, GLWESecret, - prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec, GGLWETensorKeyExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, }, noise::noise_ggsw_keyswitch, trait_families::GGSWAssertNoiseFamily, }; use crate::trait_families::{ - GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWKeySwitchFamily, GLWESecretExecModuleFamily, + GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWKeySwitchFamily, GLWESecretPreparedModuleFamily, }; pub fn test_ggsw_automorphism<B: Backend>(@@ -37,10 +37,9 @@ rank: usize,
sigma: f64, ) where Module<B>: GGSWAssertNoiseFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + VecZnxAddScalarInplace + VecZnxCopy - + VecZnxStd + VecZnxSubABInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -92,7 +91,7 @@ let var_xs: f64 = 0.5;
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); auto_key.encrypt_sk( module,@@ -117,21 +116,28 @@
ct_in.encrypt_sk( module, &pt_scalar, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut auto_key_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - auto_key_exec.prepare(module, &auto_key, scratch.borrow()); + let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank); + auto_key_prepared.prepare(module, &auto_key, scratch.borrow()); - let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); - tsk_exec.prepare(module, &tensor_key, scratch.borrow()); + let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = + GGLWETensorKeyPrepared::alloc(module, n, basek, k_tsk, rows, digits, rank); + tsk_prepared.prepare(module, &tensor_key, scratch.borrow()); - ct_out.automorphism(module, &ct_in, &auto_key_exec, &tsk_exec, scratch.borrow()); + ct_out.automorphism( + module, + &ct_in, + &auto_key_prepared, + &tsk_prepared, + scratch.borrow(), + ); module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);@@ -151,7 +157,7 @@ k_tsk,
) + 0.5 }; - ct_out.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); + ct_out.assert_noise(module, &sk_prepared, &pt_scalar, &max_noise); } pub fn test_ggsw_automorphism_inplace<B: Backend>(@@ -166,10 +172,9 @@ rank: usize,
sigma: f64, ) where Module<B>: GGSWAssertNoiseFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + VecZnxAddScalarInplace + VecZnxCopy - + VecZnxStd + VecZnxSubABInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -217,7 +222,7 @@ let var_xs: f64 = 0.5;
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(var_xs, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); auto_key.encrypt_sk( module,@@ -242,21 +247,22 @@
ct.encrypt_sk( module, &pt_scalar, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut auto_key_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - auto_key_exec.prepare(module, &auto_key, scratch.borrow()); + let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank); + auto_key_prepared.prepare(module, &auto_key, scratch.borrow()); - let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_tsk, rows, digits, rank); - tsk_exec.prepare(module, &tensor_key, scratch.borrow()); + let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = + GGLWETensorKeyPrepared::alloc(module, n, basek, k_tsk, rows, digits, rank); + tsk_prepared.prepare(module, &tensor_key, scratch.borrow()); - ct.automorphism_inplace(module, &auto_key_exec, &tsk_exec, scratch.borrow()); + ct.automorphism_inplace(module, &auto_key_prepared, &tsk_prepared, scratch.borrow()); module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);@@ -276,5 +282,5 @@ k_tsk,
) + 0.5 }; - ct.assert_noise(module, &sk_exec, &pt_scalar, &max_noise); + ct.assert_noise(module, &sk_prepared, &pt_scalar, &max_noise); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + VecZnxFillUniform, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -14,13 +14,13 @@
use crate::{ layouts::{ GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, - prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_glwe_automorphism<B: Backend>( module: &Module<B>,@@ -34,14 +34,13 @@ rank: usize,
sigma: f64, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace + VecZnxAutomorphismInplace - + VecZnxStd + VmpPMatAlloc<B> + VmpPMatPrepare<B>, B: TakeVecZnxDftImpl<B>@@ -85,7 +84,7 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); autokey.encrypt_sk( module,@@ -100,18 +99,18 @@
ct_in.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut autokey_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - autokey_exec.prepare(module, &autokey, scratch.borrow()); + let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank); + autokey_prepared.prepare(module, &autokey, scratch.borrow()); - ct_out.automorphism(module, &ct_in, &autokey_exec, scratch.borrow()); + ct_out.automorphism(module, &ct_in, &autokey_prepared, scratch.borrow()); let max_noise: f64 = log2_std_noise_gglwe_product( module.n() as f64,@@ -128,7 +127,7 @@ );
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0); - ct_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0); + ct_out.assert_noise(module, &sk_prepared, &pt_want, max_noise + 1.0); } pub fn test_glwe_automorphism_inplace<B: Backend>(@@ -142,14 +141,13 @@ rank: usize,
sigma: f64, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace + VecZnxAutomorphismInplace - + VecZnxStd + VmpPMatAlloc<B> + VmpPMatPrepare<B>, B: TakeVecZnxDftImpl<B>@@ -183,7 +181,7 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); autokey.encrypt_sk( module,@@ -198,18 +196,18 @@
ct.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut autokey_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = - GGLWEAutomorphismKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - autokey_exec.prepare(module, &autokey, scratch.borrow()); + let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = + GGLWEAutomorphismKeyPrepared::alloc(module, n, basek, k_ksk, rows, digits, rank); + autokey_prepared.prepare(module, &autokey, scratch.borrow()); - ct.automorphism_inplace(module, &autokey_exec, scratch.borrow()); + ct.automorphism_inplace(module, &autokey_prepared, scratch.borrow()); let max_noise: f64 = log2_std_noise_gglwe_product( module.n() as f64,@@ -226,5 +224,5 @@ );
module.vec_znx_automorphism_inplace(p, &mut pt_want.data, 0); - ct.assert_noise(module, &sk_exec, &pt_want, max_noise + 1.0); + ct.assert_noise(module, &sk_prepared, &pt_want, max_noise + 1.0); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, - VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, ZnxView, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -14,10 +14,10 @@
use crate::layouts::{ GLWECiphertext, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey, - prepared::{GLWESecretExec, GLWEToLWESwitchingKeyExec, LWEToGLWESwitchingKeyExec}, + prepared::{GLWESecretPrepared, GLWEToLWESwitchingKeyPrepared, LWEToGLWESwitchingKeyPrepared, PrepareAlloc}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretPreparedModuleFamily}; pub fn test_lwe_to_glwe<B: Backend>(module: &Module<B>) where@@ -26,11 +26,10 @@ + GLWEDecryptFamily<B>
+ VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWEKeyswitchFamily<B> - + VecZnxEncodeCoeffsi64 + VecZnxAutomorphismInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B> - + GLWESecretExecModuleFamily<B>, + + GLWESecretPreparedModuleFamily<B>, B: TakeScalarZnxImpl<B> + TakeVecZnxDftImpl<B> + ScratchAvailableImpl<B>@@ -67,7 +66,7 @@
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe); sk_lwe.fill_ternary_prob(0.5, &mut source_xs);@@ -75,7 +74,7 @@
let data: i64 = 17; let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut lwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + lwe_pt.encode_i64(data, k_lwe_pt); let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); lwe_ct.encrypt_sk(@@ -101,12 +100,12 @@ );
let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); - let ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = LWEToGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - glwe_ct.from_lwe(module, &lwe_ct, &ksk_exec, scratch.borrow()); + glwe_ct.from_lwe(module, &lwe_ct, &ksk_prepared, scratch.borrow()); let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); - glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_exec, scratch.borrow()); + glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_prepared, scratch.borrow()); assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]); }@@ -118,11 +117,10 @@ + GLWEDecryptFamily<B>
+ VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWEKeyswitchFamily<B> - + VecZnxEncodeCoeffsi64 + VecZnxAutomorphismInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B> - + GLWESecretExecModuleFamily<B>, + + GLWESecretPreparedModuleFamily<B>, B: TakeScalarZnxImpl<B> + TakeVecZnxDftImpl<B> + ScratchAvailableImpl<B>@@ -159,20 +157,20 @@
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let sk_glwe_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_glwe); + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let mut sk_lwe = LWESecret::alloc(n_lwe); sk_lwe.fill_ternary_prob(0.5, &mut source_xs); let data: i64 = 17; let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_glwe_ct); - module.encode_coeff_i64(basek, &mut glwe_pt.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + glwe_pt.encode_coeff_i64(data, k_lwe_pt, 0); let mut glwe_ct = GLWECiphertext::alloc(n, basek, k_glwe_ct, rank); glwe_ct.encrypt_sk( module, &glwe_pt, - &sk_glwe_exec, + &sk_glwe_prepared, &mut source_xa, &mut source_xe, sigma,@@ -193,9 +191,9 @@ );
let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe_ct); - let ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = GLWEToLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - lwe_ct.from_glwe(module, &glwe_ct, &ksk_exec, scratch.borrow()); + lwe_ct.from_glwe(module, &glwe_ct, &ksk_prepared, scratch.borrow()); let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe);
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, - VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -12,11 +12,15 @@ };
use sampling::source::Source; use crate::{ - layouts::{GGLWEAutomorphismKey, GLWESecret, compressed::GGLWEAutomorphismKeyCompressed, prepared::GLWESecretExec}, + layouts::{ + GGLWEAutomorphismKey, GLWESecret, + compressed::GGLWEAutomorphismKeyCompressed, + prepared::{GLWESecretPrepared, PrepareAlloc}, + }, trait_families::{Decompress, GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEAutomorphismKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_gglwe_automorphisk_key_encrypt_sk<B: Backend>( module: &Module<B>,@@ -27,7 +31,7 @@ rank: usize,
sigma: f64, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree@@ -36,7 +40,6 @@ + VecZnxAutomorphism
+ VecZnxAutomorphismInplace + GLWEDecryptFamily<B> + VecZnxSubScalarInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -87,11 +90,11 @@ &sk.data.as_vec_znx(),
i, ); }); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); atk.key .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); + .assert_noise(module, &sk_out_prepared, &sk.data, sigma); } pub fn test_gglwe_automorphisk_key_compressed_encrypt_sk<B: Backend>(@@ -103,7 +106,7 @@ rank: usize,
sigma: f64, ) where Module<B>: GGLWEAutomorphismKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree@@ -112,7 +115,6 @@ + VecZnxAutomorphism
+ VecZnxAutomorphismInplace + GLWEDecryptFamily<B> + VecZnxSubScalarInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -165,12 +167,12 @@ &sk.data.as_vec_znx(),
i, ); }); - let sk_out_exec = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared = sk_out.prepare_alloc(module, scratch.borrow()); let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); atk.decompress(module, &atk_compressed); atk.key .key - .assert_noise(module, &sk_out_exec, &sk.data, sigma); + .assert_noise(module, &sk_out_prepared, &sk.data, sigma); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubScalarInplace, - VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxSubScalarInplace, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -12,11 +12,15 @@ };
use sampling::source::Source; use crate::{ - layouts::{GLWESecret, GGLWESwitchingKey, compressed::GGLWESwitchingKeyCompressed, prepared::GLWESecretExec}, + layouts::{ + GGLWESwitchingKey, GLWESecret, + compressed::GGLWESwitchingKeyCompressed, + prepared::{GLWESecretPrepared, PrepareAlloc}, + }, trait_families::{Decompress, GLWEDecryptFamily}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_gglwe_switching_key_encrypt_sk<B: Backend>( module: &Module<B>,@@ -28,11 +32,10 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -67,7 +70,7 @@ sk_in.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); ksk.encrypt_sk( module,@@ -80,7 +83,7 @@ scratch.borrow(),
); ksk.key - .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); + .assert_noise(module, &sk_out_prepared, &sk_in.data, sigma); } pub fn test_gglwe_switching_key_compressed_encrypt_sk<B: Backend>(@@ -93,11 +96,10 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -132,7 +134,7 @@ sk_in.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); let seed_xa = [1u8; 32];@@ -150,5 +152,5 @@ let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
ksk.decompress(module, &ksk_compressed); ksk.key - .assert_noise(module, &sk_out_exec, &sk_in.data, sigma); + .assert_noise(module, &sk_out_prepared, &sk_in.data, sigma); }
@@ -1,6 +1,6 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubABInplace, VmpPMatAlloc, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxSubABInplace, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned},@@ -12,20 +12,23 @@ };
use sampling::source::Source; use crate::{ - layouts::{GGSWCiphertext, GLWESecret, compressed::GGSWCiphertextCompressed, prepared::GLWESecretExec}, + layouts::{ + GGSWCiphertext, GLWESecret, + compressed::GGSWCiphertextCompressed, + prepared::{GLWESecretPrepared, PrepareAlloc}, + }, trait_families::{Decompress, GGSWAssertNoiseFamily}, }; -use crate::trait_families::{GGSWEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGSWEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_ggsw_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, digits: usize, rank: usize, sigma: f64) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -60,13 +63,12 @@ ));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); ct.encrypt_sk( module, &pt_scalar, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma,@@ -75,7 +77,7 @@ );
let noise_f = |_col_i: usize| -(k as f64) + sigma.log2() + 0.5; - ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); + ct.assert_noise(module, &sk_prepared, &pt_scalar, &noise_f); } pub fn test_ggsw_compressed_encrypt_sk<B: Backend>(@@ -86,12 +88,11 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>,@@ -125,15 +126,14 @@ ));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); let seed_xa: [u8; 32] = [1u8; 32]; ct_compressed.encrypt_sk( module, &pt_scalar, - &sk_exec, + &sk_prepared, seed_xa, &mut source_xe, sigma,@@ -145,5 +145,5 @@
let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k, rows, digits, rank); ct.decompress(module, &ct_compressed); - ct.assert_noise(module, &sk_exec, &pt_scalar, &noise_f); + ct.assert_noise(module, &sk_prepared, &pt_scalar, &noise_f); }
@@ -1,5 +1,5 @@
use backend::hal::{ - api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxCopy, VecZnxDftAlloc, VecZnxFillUniform, VecZnxStd, VecZnxSubABInplace}, + api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxCopy, VecZnxDftAlloc, VecZnxFillUniform, VecZnxSubABInplace}, layouts::{Backend, Module, ScratchOwned}, oep::{ ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,@@ -12,16 +12,16 @@ use crate::{
layouts::{ GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos, compressed::GLWECiphertextCompressed, - prepared::{GLWEPublicKeyExec, GLWESecretExec}, + prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, operations::GLWEOperations, trait_families::Decompress, }; -use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub trait EncryptionTestModuleFamily<B: Backend> = - GLWEDecryptFamily<B> + VecZnxStd + GLWESecretExecModuleFamily<B> + GLWEEncryptPkFamily<B>; + GLWEDecryptFamily<B> + GLWESecretPreparedModuleFamily<B> + GLWEEncryptPkFamily<B>; pub fn test_glwe_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize) where@@ -51,25 +51,25 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa); ct.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); pt_want.sub_inplace_ab(module, &pt_have); - let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0) * (ct.k() as f64).exp2(); + let noise_have: f64 = pt_want.data.std(basek, 0) * (ct.k() as f64).exp2(); let noise_want: f64 = sigma; assert!(noise_have <= noise_want + 0.2);@@ -110,7 +110,7 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa);@@ -119,7 +119,7 @@
ct_compressed.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, seed_xa, &mut source_xe, sigma,@@ -129,11 +129,11 @@
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); ct.decompress(module, &ct_compressed); - ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); pt_want.sub_inplace_ab(module, &pt_have); - let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0) * (ct.k() as f64).exp2(); + let noise_have: f64 = pt_want.data.std(basek, 0) * (ct.k() as f64).exp2(); let noise_want: f64 = sigma; assert!(@@ -163,28 +163,28 @@ let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([1u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); - sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( GLWECiphertext::decrypt_scratch_space(module, n, basek, k_ct) | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct), ); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk.fill_ternary_prob(0.5, &mut source_xs); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); + + let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank); + ct.encrypt_zero_sk( module, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - ct.decrypt(module, &mut pt, &sk_exec, scratch.borrow()); + ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow()); - assert!((sigma - module.vec_znx_std(basek, &pt.data, 0) * (k_ct as f64).exp2()) <= 0.2); + assert!((sigma - pt.data.std(basek, 0) * (k_ct as f64).exp2()) <= 0.2); } pub fn test_glwe_encrypt_pk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize)@@ -210,38 +210,38 @@ let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]); let mut source_xu: Source = Source::new([0u8; 32]); + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( + GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k()) + | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k()) + | GLWECiphertext::encrypt_pk_scratch_space(module, n, basek, k_pk), + ); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc(n, basek, k_pk, rank); - pk.generate_from_sk(module, &sk_exec, &mut source_xa, &mut source_xe, sigma); - - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k()) - | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k()) - | GLWECiphertext::encrypt_pk_scratch_space(module, n, basek, pk.k()), - ); + pk.generate_from_sk(module, &sk_prepared, &mut source_xa, &mut source_xe, sigma); module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa); - let pk_exec: GLWEPublicKeyExec<Vec<u8>, B> = GLWEPublicKeyExec::from(module, &pk, scratch.borrow()); + let pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = pk.prepare_alloc(module, scratch.borrow()); ct.encrypt_pk( module, &pt_want, - &pk_exec, + &pk_prepared, &mut source_xu, &mut source_xe, sigma, scratch.borrow(), ); - ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow()); + ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow()); pt_want.sub_inplace_ab(module, &pt_have); - let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0).log2(); + let noise_have: f64 = pt_want.data.std(basek, 0).log2(); let noise_want: f64 = ((((rank as f64) + 1.0) * n as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64); assert!(
@@ -1,6 +1,6 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxStd, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned, VecZnxDft},@@ -12,20 +12,23 @@ };
use sampling::source::Source; use crate::{ - layouts::{GGLWETensorKey, GLWEPlaintext, GLWESecret, Infos, compressed::GGLWETensorKeyCompressed, prepared::GLWESecretExec}, + layouts::{ + GGLWETensorKey, GLWEPlaintext, GLWESecret, Infos, + compressed::GGLWETensorKeyCompressed, + prepared::{GLWESecretPrepared, PrepareAlloc}, + }, trait_families::{Decompress, GLWEDecryptFamily}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_glwe_tensor_key_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -64,8 +67,7 @@ ));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); tensor_key.encrypt_sk( module,@@ -89,7 +91,7 @@ });
(0..rank).for_each(|i| { (0..rank).for_each(|j| { - module.svp_apply(&mut sk_ij_dft, 0, &sk_exec.data, j, &sk_dft, i); + module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i); module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); module.vec_znx_big_normalize( basek,@@ -104,11 +106,11 @@ (0..tensor_key.rows()).for_each(|row_i| {
tensor_key .at(i, j) .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_exec, scratch.borrow()); + .decrypt(module, &mut pt, &sk_prepared, scratch.borrow()); module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i); - let std_pt: f64 = module.vec_znx_std(basek, &pt.data, 0) * (k as f64).exp2(); + let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2(); assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt); }); });@@ -119,11 +121,10 @@
pub fn test_glwe_tensor_key_compressed_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -147,7 +148,8 @@ {
let n: usize = module.n(); let rows: usize = k / basek; - let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank); + let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> = + GGLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);@@ -162,8 +164,7 @@ ));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); - sk_exec.prepare(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); let seed_xa: [u8; 32] = [1u8; 32];@@ -192,7 +193,7 @@ });
(0..rank).for_each(|i| { (0..rank).for_each(|j| { - module.svp_apply(&mut sk_ij_dft, 0, &sk_exec.data, j, &sk_dft, i); + module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i); module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); module.vec_znx_big_normalize( basek,@@ -207,11 +208,11 @@ (0..tensor_key.rows()).for_each(|row_i| {
tensor_key .at(i, j) .at(row_i, col_i) - .decrypt(module, &mut pt, &sk_exec, scratch.borrow()); + .decrypt(module, &mut pt, &sk_prepared, scratch.borrow()); module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i); - let std_pt: f64 = module.vec_znx_std(basek, &pt.data, 0) * (k as f64).exp2(); + let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2(); assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt); }); });
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, - VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxSubScalarInplace, + VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, }, layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, oep::{@@ -13,14 +13,14 @@ use sampling::source::Source;
use crate::{ layouts::{ - GGSWCiphertext, GLWESecret, GGLWESwitchingKey, - prepared::{GGSWCiphertextExec, GLWESecretExec}, + GGLWESwitchingKey, GGSWCiphertext, GLWESecret, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, trait_families::{GLWEDecryptFamily, GLWEExternalProductFamily}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_gglwe_switching_key_external_product<B: Backend>( module: &Module<B>,@@ -34,11 +34,10 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -63,7 +62,8 @@ let n: usize = module.n();
let rows: usize = k_in.div_ceil(basek * digits); let digits_in: usize = 1; - let mut ct_gglwe_in: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); + let mut ct_gglwe_in: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out); let mut ct_gglwe_out: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out); let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out);@@ -91,7 +91,7 @@ sk_in.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); // gglwe_{s1}(s0) = s0 -> s1 ct_gglwe_in.encrypt_sk(@@ -107,20 +107,17 @@
ct_rgsw.encrypt_sk( module, &pt_rgsw, - &sk_out_exec, + &sk_out_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = - GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); - - ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); + let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) - ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_exec, scratch.borrow()); + ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_prepared, scratch.borrow()); (0..rank_in).for_each(|i| { module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r}@@ -149,7 +146,7 @@ );
ct_gglwe_out .key - .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); + .assert_noise(module, &sk_out_prepared, &sk_in.data, max_noise + 0.5); } pub fn test_gglwe_switching_key_external_product_inplace<B: Backend>(@@ -163,11 +160,10 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -219,7 +215,7 @@ sk_in.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); // gglwe_{s1}(s0) = s0 -> s1 ct_gglwe.encrypt_sk(@@ -235,20 +231,17 @@
ct_rgsw.encrypt_sk( module, &pt_rgsw, - &sk_out_exec, + &sk_out_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> = - GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out); - - ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow()); + let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) - ct_gglwe.external_product_inplace(module, &ct_rgsw_exec, scratch.borrow()); + ct_gglwe.external_product_inplace(module, &ct_rgsw_prepared, scratch.borrow()); (0..rank_in).for_each(|i| { module.vec_znx_rotate_inplace(r as i64, &mut sk_in.data.as_vec_znx_mut(), i); // * X^{r}@@ -277,5 +270,5 @@ );
ct_gglwe .key - .assert_noise(module, &sk_out_exec, &sk_in.data, max_noise + 0.5); + .assert_noise(module, &sk_out_prepared, &sk_in.data, max_noise + 0.5); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, - VecZnxSubABInplace, VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxSubABInplace, + VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, }, layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned}, oep::{@@ -14,7 +14,7 @@
use crate::{ layouts::{ GGSWCiphertext, GLWESecret, - prepared::{GGSWCiphertextExec, GLWESecretExec}, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, trait_families::GGSWAssertNoiseFamily,@@ -22,7 +22,7 @@ };
use crate::trait_families::{ GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWEncryptSkFamily, GGSWKeySwitchFamily, - GLWESecretExecModuleFamily, + GLWESecretPreparedModuleFamily, }; pub fn test_ggsw_external_product<B: Backend>(@@ -35,12 +35,11 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -89,12 +88,12 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); ct_ggsw_rhs.encrypt_sk( module, &pt_ggsw_rhs, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma,@@ -104,17 +103,16 @@
ct_ggsw_lhs_in.encrypt_sk( module, &pt_ggsw_lhs, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); - ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); + let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw_rhs.prepare_alloc(module, scratch.borrow()); - ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_exec, scratch.borrow()); + ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_prepared, scratch.borrow()); module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);@@ -141,7 +139,7 @@ k_ggsw,
) + 0.5 }; - ct_ggsw_lhs_out.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); + ct_ggsw_lhs_out.assert_noise(module, &sk_prepared, &pt_ggsw_lhs, &max_noise); } pub fn test_ggsw_external_product_inplace<B: Backend>(@@ -153,12 +151,11 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -207,12 +204,12 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); ct_ggsw_rhs.encrypt_sk( module, &pt_ggsw_rhs, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma,@@ -222,17 +219,16 @@
ct_ggsw_lhs.encrypt_sk( module, &pt_ggsw_lhs, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let mut ct_rhs_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank); - ct_rhs_exec.prepare(module, &ct_ggsw_rhs, scratch.borrow()); + let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw_rhs.prepare_alloc(module, scratch.borrow()); - ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_exec, scratch.borrow()); + ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_prepared, scratch.borrow()); module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);@@ -259,5 +255,5 @@ k_ggsw,
) + 0.5 }; - ct_ggsw_lhs.assert_noise(module, &sk_exec, &pt_ggsw_lhs, &max_noise); + ct_ggsw_lhs.assert_noise(module, &sk_prepared, &pt_ggsw_lhs, &max_noise); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxRotateInplace, VecZnxStd, - VmpPMatAlloc, VmpPMatPrepare, ZnxViewMut, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxRotateInplace, VmpPMatAlloc, + VmpPMatPrepare, ZnxViewMut, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{@@ -14,12 +14,12 @@
use crate::{ layouts::{ GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, - prepared::{GGSWCiphertextExec, GLWESecretExec}, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, }; -use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptSkFamily, GLWEExternalProductFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GLWEDecryptFamily, GLWEEncryptSkFamily, GLWEExternalProductFamily, GLWESecretPreparedModuleFamily}; pub fn test_glwe_external_product<B: Backend>( module: &Module<B>,@@ -32,12 +32,11 @@ rank: usize,
sigma: f64, ) where Module<B>: GLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + GLWEExternalProductFamily<B> + VecZnxAddScalarInplace + VecZnxRotateInplace - + VecZnxStd + VmpPMatAlloc<B> + VmpPMatPrepare<B>, B: TakeVecZnxDftImpl<B>@@ -88,12 +87,12 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); ct_ggsw.encrypt_sk( module, &pt_rgsw, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma,@@ -103,16 +102,16 @@
ct_glwe_in.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let ct_ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::from(module, &ct_ggsw, scratch.borrow()); + let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw.prepare_alloc(module, scratch.borrow()); - ct_glwe_out.external_product(module, &ct_glwe_in, &ct_ggsw_exec, scratch.borrow()); + ct_glwe_out.external_product(module, &ct_glwe_in, &ct_ggsw_prepared, scratch.borrow()); module.vec_znx_rotate_inplace(k as i64, &mut pt_want.data, 0);@@ -137,7 +136,7 @@ k_in,
k_ggsw, ); - ct_glwe_out.assert_noise(module, &sk_exec, &pt_want, max_noise + 0.5); + ct_glwe_out.assert_noise(module, &sk_prepared, &pt_want, max_noise + 0.5); } pub fn test_glwe_external_product_inplace<B: Backend>(@@ -150,12 +149,11 @@ rank: usize,
sigma: f64, ) where Module<B>: GLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + GLWEExternalProductFamily<B> + VecZnxAddScalarInplace + VecZnxRotateInplace - + VecZnxStd + VmpPMatAlloc<B> + VmpPMatPrepare<B>, B: TakeVecZnxDftImpl<B>@@ -196,12 +194,12 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); ct_ggsw.encrypt_sk( module, &pt_rgsw, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma,@@ -211,16 +209,16 @@
ct_glwe.encrypt_sk( module, &pt_want, - &sk_exec, + &sk_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let ct_ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = GGSWCiphertextExec::from(module, &ct_ggsw, scratch.borrow()); + let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_ggsw.prepare_alloc(module, scratch.borrow()); - ct_glwe.external_product_inplace(module, &ct_ggsw_exec, scratch.borrow()); + ct_glwe.external_product_inplace(module, &ct_ggsw_prepared, scratch.borrow()); module.vec_znx_rotate_inplace(k as i64, &mut pt_want.data, 0);@@ -245,5 +243,5 @@ k_ct,
k_ggsw, ); - ct_glwe.assert_noise(module, &sk_exec, &pt_want, max_noise + 0.5); + ct_glwe.assert_noise(module, &sk_prepared, &pt_want, max_noise + 0.5); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubScalarInplace, - VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxSubScalarInplace, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -13,14 +13,14 @@ use sampling::source::Source;
use crate::{ layouts::{ - GLWESecret, GGLWESwitchingKey, - prepared::{GLWESecretExec, GGLWESwitchingKeyExec}, + GGLWESwitchingKey, GLWESecret, + prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_gglwe_switching_key_keyswitch<B: Backend>( module: &Module<B>,@@ -35,11 +35,10 @@ rank_out_s1s2: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -109,7 +108,7 @@ sk1.fill_ternary_prob(0.5, &mut source_xs);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s1s2); sk2.fill_ternary_prob(0.5, &mut source_xs); - let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); + let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) = s0 -> s1 ct_gglwe_s0s1.encrypt_sk(@@ -133,14 +132,14 @@ sigma,
scratch_enc.borrow(), ); - let ct_gglwe_s1s2_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = - GGLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); + let ct_gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = + ct_gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) ct_gglwe_s0s2.keyswitch( module, &ct_gglwe_s0s1, - &ct_gglwe_s1s2_exec, + &ct_gglwe_s1s2_prepared, scratch_apply.borrow(), );@@ -159,7 +158,7 @@ );
ct_gglwe_s0s2 .key - .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); + .assert_noise(module, &sk2_prepared, &sk0.data, max_noise + 0.5); } pub fn test_gglwe_switching_key_keyswitch_inplace<B: Backend>(@@ -173,11 +172,10 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWEEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEDecryptFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxStd + VecZnxSubScalarInplace + VecZnxCopy + VmpPMatAlloc<B>@@ -203,7 +201,8 @@ let digits_in: usize = 1;
let mut ct_gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out); - let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out); + let mut ct_gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = + GGLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);@@ -231,7 +230,7 @@ sk1.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk2.fill_ternary_prob(var_xs, &mut source_xs); - let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2); + let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) = s0 -> s1 ct_gglwe_s0s1.encrypt_sk(@@ -255,11 +254,11 @@ sigma,
scratch_enc.borrow(), ); - let ct_gglwe_s1s2_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = - GGLWESwitchingKeyExec::from(module, &ct_gglwe_s1s2, scratch_apply.borrow()); + let ct_gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = + ct_gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) - ct_gglwe_s0s1.keyswitch_inplace(module, &ct_gglwe_s1s2_exec, scratch_apply.borrow()); + ct_gglwe_s0s1.keyswitch_inplace(module, &ct_gglwe_s1s2_prepared, scratch_apply.borrow()); let ct_gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = ct_gglwe_s0s1;@@ -278,5 +277,5 @@ );
ct_gglwe_s0s2 .key - .assert_noise(module, &sk2_exec, &sk0.data, max_noise + 0.5); + .assert_noise(module, &sk2_prepared, &sk0.data, max_noise + 0.5); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxStd, VecZnxSubABInplace, - VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxSubABInplace, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{@@ -13,8 +13,8 @@ use sampling::source::Source;
use crate::{ layouts::{ - GGLWETensorKey, GGSWCiphertext, GLWESecret, GGLWESwitchingKey, - prepared::{GLWESecretExec, GGLWESwitchingKeyExec, GGLWETensorKeyExec}, + GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GLWESecret, + prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_keyswitch, trait_families::GGSWAssertNoiseFamily,@@ -22,7 +22,7 @@ };
use crate::trait_families::{ GGLWESwitchingKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWEncryptSkFamily, GGSWKeySwitchFamily, - GLWESecretExecModuleFamily, + GLWESecretPreparedModuleFamily, }; pub fn test_ggsw_keyswitch<B: Backend>(@@ -36,12 +36,11 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -93,11 +92,11 @@ let var_xs: f64 = 0.5;
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); ksk.encrypt_sk( module,@@ -129,14 +128,16 @@ sigma,
scratch.borrow(), ); - let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = - GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - - ksk_exec.prepare(module, &ksk, scratch.borrow()); - tsk_exec.prepare(module, &tsk, scratch.borrow()); + let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); + let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); - ct_out.keyswitch(module, &ct_in, &ksk_exec, &tsk_exec, scratch.borrow()); + ct_out.keyswitch( + module, + &ct_in, + &ksk_prepared, + &tsk_prepared, + scratch.borrow(), + ); let max_noise = |col_j: usize| -> f64 { noise_ggsw_keyswitch(@@ -154,7 +155,7 @@ k_tsk,
) + 0.5 }; - ct_out.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); + ct_out.assert_noise(module, &sk_out_prepared, &pt_scalar, &max_noise); } pub fn test_ggsw_keyswitch_inplace<B: Backend>(@@ -167,12 +168,11 @@ digits: usize,
rank: usize, sigma: f64, ) where - Module<B>: GLWESecretExecModuleFamily<B> + Module<B>: GLWESecretPreparedModuleFamily<B> + GGSWEncryptSkFamily<B> + GGSWAssertNoiseFamily<B> + VecZnxAddScalarInplace + VecZnxSubABInplace - + VecZnxStd + VecZnxCopy + VmpPMatAlloc<B> + VmpPMatPrepare<B>@@ -218,11 +218,11 @@ let var_xs: f64 = 0.5;
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let sk_in_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_out.fill_ternary_prob(var_xs, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); ksk.encrypt_sk( module,@@ -254,14 +254,10 @@ sigma,
scratch.borrow(), ); - let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = - GGLWESwitchingKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank, rank); - let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = GGLWETensorKeyExec::alloc(module, n, basek, k_ksk, rows, digits, rank); - - ksk_exec.prepare(module, &ksk, scratch.borrow()); - tsk_exec.prepare(module, &tsk, scratch.borrow()); + let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); + let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); - ct.keyswitch_inplace(module, &ksk_exec, &tsk_exec, scratch.borrow()); + ct.keyswitch_inplace(module, &ksk_prepared, &tsk_prepared, scratch.borrow()); let max_noise = |col_j: usize| -> f64 { noise_ggsw_keyswitch(@@ -279,5 +275,5 @@ k_tsk,
) + 0.5 }; - ct.assert_noise(module, &sk_out_exec, &pt_scalar, &max_noise); + ct.assert_noise(module, &sk_out_prepared, &pt_scalar, &max_noise); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxStd, VecZnxSwithcDegree, - VmpPMatAlloc, VmpPMatPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxSwithcDegree, VmpPMatAlloc, + VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -13,14 +13,14 @@ use sampling::source::Source;
use crate::{ layouts::{ - GLWECiphertext, GLWEPlaintext, GLWESecret, GGLWESwitchingKey, Infos, - prepared::{GLWESecretExec, GGLWESwitchingKeyExec}, + GGLWESwitchingKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, + prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub fn test_glwe_keyswitch<B: Backend>( module: &Module<B>,@@ -34,10 +34,9 @@ rank_out: usize,
sigma: f64, ) where Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace + VmpPMatAlloc<B>@@ -83,11 +82,11 @@ );
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let sk_in_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out); sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); ksk.encrypt_sk( module,@@ -102,16 +101,16 @@
ct_in.encrypt_sk( module, &pt_want, - &sk_in_exec, + &sk_in_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - ct_out.keyswitch(module, &ct_in, &ksk_exec, scratch.borrow()); + ct_out.keyswitch(module, &ct_in, &ksk_prepared, scratch.borrow()); let max_noise: f64 = log2_std_noise_gglwe_product( module.n() as f64,@@ -126,7 +125,7 @@ k_in,
k_ksk, ); - ct_out.assert_noise(module, &sk_out_exec, &pt_want, max_noise + 0.5); + ct_out.assert_noise(module, &sk_out_prepared, &pt_want, max_noise + 0.5); } pub fn test_glwe_keyswitch_inplace<B: Backend>(@@ -139,10 +138,9 @@ rank: usize,
sigma: f64, ) where Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace + VmpPMatAlloc<B>@@ -177,11 +175,11 @@ );
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let sk_in_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_in); + let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk_out.fill_ternary_prob(0.5, &mut source_xs); - let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out); + let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow()); ksk.encrypt_sk( module,@@ -196,16 +194,16 @@
ct_glwe.encrypt_sk( module, &pt_want, - &sk_in_exec, + &sk_in_prepared, &mut source_xa, &mut source_xe, sigma, scratch.borrow(), ); - let ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = GGLWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - ct_glwe.keyswitch_inplace(module, &ksk_exec, scratch.borrow()); + ct_glwe.keyswitch_inplace(module, &ksk_prepared, scratch.borrow()); let max_noise: f64 = log2_std_noise_gglwe_product( module.n() as f64,@@ -220,5 +218,5 @@ k_ct,
k_ksk, ); - ct_glwe.assert_noise(module, &sk_out_exec, &pt_want, max_noise + 0.5); + ct_glwe.assert_noise(module, &sk_out_prepared, &pt_want, max_noise + 0.5); }
@@ -1,7 +1,7 @@
use backend::hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxEncodeCoeffsi64, - VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxSwithcDegree, + VmpPMatAlloc, VmpPMatPrepare, ZnxView, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -11,9 +11,12 @@ },
}; use sampling::source::Source; -use crate::layouts::{Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey, prepared::LWESwitchingKeyExec}; +use crate::layouts::{ + Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey, + prepared::{LWESwitchingKeyPrepared, PrepareAlloc}, +}; -use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWEEncryptSkFamily, GLWEDecryptFamily, GLWEKeyswitchFamily, GLWESecretPreparedModuleFamily}; pub fn test_lwe_keyswitch<B: Backend>(module: &Module<B>) where@@ -22,11 +25,10 @@ + GLWEDecryptFamily<B>
+ VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWEKeyswitchFamily<B> - + VecZnxEncodeCoeffsi64 + VecZnxAutomorphismInplace + VmpPMatAlloc<B> + VmpPMatPrepare<B> - + GLWESecretExecModuleFamily<B>, + + GLWESecretPreparedModuleFamily<B>, B: TakeScalarZnxImpl<B> + TakeVecZnxDftImpl<B> + ScratchAvailableImpl<B>@@ -65,7 +67,8 @@
let data: i64 = 17; let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt); - module.encode_coeff_i64(basek, &mut lwe_pt_in.data, 0, k_lwe_pt, 0, data, k_lwe_pt); + + lwe_pt_in.encode_i64(data, k_lwe_pt); let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct); lwe_ct_in.encrypt_sk(@@ -91,9 +94,9 @@ );
let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct); - let ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = LWESwitchingKeyExec::from(module, &ksk, scratch.borrow()); + let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_exec, scratch.borrow()); + lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow()); let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct); lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
@@ -3,7 +3,7 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigSubSmallBInplace, - VecZnxEncodeVeci64, VecZnxRotateInplace, VecZnxStd, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + VecZnxRotateInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -17,22 +17,20 @@ use crate::{
GLWEOperations, GLWEPacker, layouts::{ GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, - prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily, GLWEPackingFamily}, }; -use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub trait PackingTestModuleFamily<B: Backend> = GLWEPackingFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GGLWESwitchingKeyEncryptSkFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxEncodeVeci64 + VecZnxRotateInplace + VecZnxAutomorphism + VecZnxBigSubSmallBInplace<B>@@ -76,7 +74,7 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct); let mut data: Vec<i64> = vec![0i64; n];@@ -84,11 +82,11 @@ data.iter_mut().enumerate().for_each(|(i, x)| {
*x = i as i64; }); - module.encode_vec_i64(basek, &mut pt.data, 0, pt_k, &data, 32); + pt.encode_vec_i64(&data, pt_k); let gal_els: Vec<i64> = GLWEPacker::galois_elements(module); - let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); + let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk(@@ -100,8 +98,8 @@ &mut source_xe,
sigma, scratch.borrow(), ); - let atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); - auto_keys.insert(*gal_el, atk_exec); + let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); + auto_keys.insert(*gal_el, atk_prepared); }); let log_batch: usize = 0;@@ -158,13 +156,13 @@ *x = reverse_bits_msb(i, log_n as u32) as i64;
} }); - module.encode_vec_i64(basek, &mut pt_want.data, 0, pt_k, &data, 32); + pt_want.encode_vec_i64(&data, pt_k); res.decrypt(module, &mut pt, &sk_dft, scratch.borrow()); pt.sub_inplace_ab(module, &pt_want); - let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2(); + let noise_have: f64 = pt.std().log2(); // println!("noise_have: {}", noise_have); assert!( noise_have < -((k_ct - basek) as f64),
@@ -3,9 +3,8 @@
use backend::hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigAutomorphismInplace, - VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxEncodeVeci64, VecZnxFillUniform, VecZnxNormalizeInplace, - VecZnxRotateInplace, VecZnxRshInplace, VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, - ZnxView, ZnxViewMut, + VecZnxBigSubSmallBInplace, VecZnxCopy, VecZnxFillUniform, VecZnxNormalizeInplace, VecZnxRotateInplace, VecZnxRshInplace, + VecZnxSubABInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, ZnxViewMut, }, layouts::{Backend, Module, ScratchOwned}, oep::{@@ -18,22 +17,20 @@
use crate::{ layouts::{ GGLWEAutomorphismKey, GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, - prepared::{GGLWEAutomorphismKeyExec, GLWESecretExec}, + prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::var_noise_gglwe_product, trait_families::{GLWEDecryptFamily, GLWEKeyswitchFamily}, }; -use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretExecModuleFamily}; +use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily}; pub trait TraceTestModuleFamily<B: Backend> = GGLWESwitchingKeyEncryptSkFamily<B> - + GLWESecretExecModuleFamily<B> + + GLWESecretPreparedModuleFamily<B> + GLWEKeyswitchFamily<B> + GLWEDecryptFamily<B> - + VecZnxStd + VecZnxSwithcDegree + VecZnxAddScalarInplace - + VecZnxEncodeVeci64 + VecZnxRotateInplace + VecZnxBigSubSmallBInplace<B> + VecZnxBigAutomorphismInplace<B>@@ -80,7 +77,7 @@ );
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); sk.fill_ternary_prob(0.5, &mut source_xs); - let sk_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk); + let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); let mut data_want: Vec<i64> = vec![0i64; n];@@ -100,7 +97,7 @@ sigma,
scratch.borrow(), ); - let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyExec<Vec<u8>, B>> = HashMap::new(); + let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module); let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(n, basek, k_autokey, rows, digits, rank); gal_els.iter().for_each(|gal_el| {@@ -113,8 +110,8 @@ &mut source_xe,
sigma, scratch.borrow(), ); - let atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = GGLWEAutomorphismKeyExec::from(module, &tmp, scratch.borrow()); - auto_keys.insert(*gal_el, atk_exec); + let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); + auto_keys.insert(*gal_el, atk_prepared); }); ct.trace_inplace(module, 0, 5, &auto_keys, scratch.borrow());@@ -127,7 +124,7 @@
module.vec_znx_sub_ab_inplace(&mut pt_want.data, 0, &pt_have.data, 0); module.vec_znx_normalize_inplace(basek, &mut pt_want.data, 0, scratch.borrow()); - let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0).log2(); + let noise_have: f64 = pt_want.std().log2(); let mut noise_want: f64 = var_noise_gglwe_product( n as f64,
@@ -1,11 +1,11 @@
use backend::hal::tests::serialization::test_reader_writer_interface; use crate::layouts::{ - GGLWEAutomorphismKey, GGLWECiphertext, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GGLWESwitchingKey, + GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GLWECiphertext, GLWEToLWESwitchingKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, compressed::{ - GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGSWCiphertextCompressed, GLWECiphertextCompressed, - GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed, + GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed, + GGSWCiphertextCompressed, GLWECiphertextCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed, LWESwitchingKeyCompressed, LWEToGLWESwitchingKeyCompressed, }, };
@@ -89,8 +89,8 @@ + VecZnxRotate
+ VecZnxAutomorphismInplace + VecZnxBigSubSmallBInplace<B> + VecZnxBigAutomorphismInplace<B>; -pub trait GLWESecretExecModuleFamily<B: Backend> = SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>; -pub trait GGLWEExecLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; +pub trait GLWESecretPreparedModuleFamily<B: Backend> = SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>; +pub trait GGLWEPreparedLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>; pub trait GLWETraceModuleFamily<B: Backend> = GLWEKeyswitchFamily<B> + VecZnxCopy + VecZnxRshInplace + VecZnxBigAutomorphismInplace<B>; pub trait GLWETraceScratchFamily<B: Backend> = TakeVecZnxDft<B> + ScratchAvailable;
@@ -0,0 +1,55 @@
+use crate::layouts::{GLWEPlaintext, Infos, LWEPlaintext}; +use backend::hal::layouts::{DataMut, DataRef}; +use rug::Float; + +impl<D: DataMut> GLWEPlaintext<D> { + pub fn encode_vec_i64(&mut self, data: &[i64], k: usize) { + let basek: usize = self.basek(); + self.data + .encode_vec_i64(basek, 0, k, data, i64::BITS as usize); + } + + pub fn encode_coeff_i64(&mut self, data: i64, k: usize, idx: usize) { + let basek: usize = self.basek(); + self.data + .encode_coeff_i64(basek, 0, k, idx, data, i64::BITS as usize); + } +} + +impl<D: DataRef> GLWEPlaintext<D> { + pub fn decode_vec_i64(&self, data: &mut [i64], k: usize) { + self.data.decode_vec_i64(self.basek(), 0, k, data); + } + + pub fn decode_coeff_i64(&self, k: usize, idx: usize) -> i64 { + self.data.decode_coeff_i64(self.basek(), 0, k, idx) + } + + pub fn decode_vec_float(&self, data: &mut [Float]) { + self.data.decode_vec_float(self.basek(), 0, data); + } + + pub fn std(&self) -> f64 { + self.data.std(self.basek(), 0) + } +} + +impl<D: DataMut> LWEPlaintext<D> { + pub fn encode_i64(&mut self, data: i64, k: usize) { + let basek: usize = self.basek(); + self.data + .encode_coeff_i64(basek, 0, k, 0, data, i64::BITS as usize); + } +} + +impl<D: DataRef> LWEPlaintext<D> { + pub fn decode_i64(&self, k: usize) -> i64 { + self.data.decode_coeff_i64(self.basek(), 0, k, 0) + } + + pub fn decode_float(&self) -> Float { + let mut data: Vec<Float> = vec![Float::new(self.k() as u32)]; + self.data.decode_vec_float(self.basek(), 0, &mut data); + data[0].clone() + } +}
@@ -0,0 +1,11 @@
+[package] +name = "schemes" +version = "0.1.0" +edition = "2024" + +[dependencies] +backend = {path="../backend"} +core = {path="../core"} +sampling = {path="../sampling"} +itertools = "0.14.0" +byteorder = "1.5.0"
@@ -0,0 +1,188 @@
+use backend::hal::{ + api::{ + ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VmpPMatAlloc, VmpPMatPrepare, ZnxView, ZnxViewMut, + }, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch}, +}; +use sampling::source::Source; + +use std::marker::PhantomData; + +use core::{ + Distribution, + layouts::{ + GGSWCiphertext, LWESecret, + compressed::GGSWCiphertextCompressed, + prepared::{GGSWCiphertextPrepared, GLWESecretPrepared}, + }, + trait_families::GGSWEncryptSkFamily, +}; + +use crate::tfhe::blind_rotation::{ + BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared, + BlindRotationKeyPreparedAlloc, CGGI, +}; + +impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> { + fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { + let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe); + (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank))); + Self { + keys: data, + dist: Distribution::NONE, + _phantom: PhantomData, + } + } +} + +impl BlindRotationKey<Vec<u8>, CGGI> { + pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGSWEncryptSkFamily<B>, + { + GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank) + } +} + +impl<D: DataMut, B: Backend> BlindRotationKeyEncryptSk<B> for BlindRotationKey<D, CGGI> +where + Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +{ + fn encrypt_sk<DataSkGLWE, DataSkLWE>( + &mut self, + module: &Module<B>, + sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>, + sk_lwe: &LWESecret<DataSkLWE>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DataSkGLWE: DataRef, + DataSkLWE: DataRef, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.keys.len(), sk_lwe.n()); + assert!(sk_glwe.n() <= module.n()); + assert_eq!(sk_glwe.rank(), self.keys[0].rank()); + match sk_lwe.dist() { + Distribution::BinaryBlock(_) + | Distribution::BinaryFixed(_) + | Distribution::BinaryProb(_) + | Distribution::ZERO => {} + _ => panic!( + "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" + ), + } + } + + self.dist = sk_lwe.dist(); + + let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1); + let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref(); + + self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| { + pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i]; + ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, sigma, scratch); + }); + } +} + +impl<B: Backend> BlindRotationKeyPreparedAlloc<B> for BlindRotationKeyPrepared<Vec<u8>, CGGI, B> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, +{ + fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { + let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(n_lwe); + (0..n_lwe).for_each(|_| { + data.push(GGSWCiphertextPrepared::alloc( + module, n_glwe, basek, k, rows, 1, rank, + )) + }); + Self { + data, + dist: Distribution::NONE, + x_pow_a: None, + _phantom: PhantomData, + } + } +} + +impl BlindRotationKeyCompressed<Vec<u8>, CGGI> { + pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self { + let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(n_lwe); + (0..n_lwe).for_each(|_| { + data.push(GGSWCiphertextCompressed::alloc( + n_gglwe, basek, k, rows, 1, rank, + )) + }); + Self { + keys: data, + dist: Distribution::NONE, + _phantom: PhantomData, + } + } + + pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize + where + Module<B>: GGSWEncryptSkFamily<B>, + { + GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank) + } +} + +impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> { + pub fn encrypt_sk<DataSkGLWE, DataSkLWE, B: Backend>( + &mut self, + module: &Module<B>, + sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>, + sk_lwe: &LWESecret<DataSkLWE>, + seed_xa: [u8; 32], + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DataSkGLWE: DataRef, + DataSkLWE: DataRef, + Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + { + #[cfg(debug_assertions)] + { + assert_eq!(self.keys.len(), sk_lwe.n()); + assert!(sk_glwe.n() <= module.n()); + assert_eq!(sk_glwe.rank(), self.keys[0].rank()); + match sk_lwe.dist() { + Distribution::BinaryBlock(_) + | Distribution::BinaryFixed(_) + | Distribution::BinaryProb(_) + | Distribution::ZERO => {} + _ => panic!( + "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)" + ), + } + } + + self.dist = sk_lwe.dist(); + + let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1); + let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref(); + + let mut source_xa: Source = Source::new(seed_xa); + + self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| { + pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i]; + ggsw.encrypt_sk( + module, + &pt, + sk_glwe, + source_xa.new_seed(), + source_xe, + sigma, + scratch, + ); + }); + } +}
@@ -0,0 +1,162 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, Scratch, WriterTo}, +}; +use sampling::source::Source; + +use std::{fmt, marker::PhantomData}; + +use core::{ + Distribution, + layouts::{GGSWCiphertext, Infos, LWESecret, prepared::GLWESecretPrepared}, +}; + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use crate::tfhe::blind_rotation::BlindRotationAlgo; + +pub trait BlindRotationKeyAlloc { + fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self; +} + +pub trait BlindRotationKeyEncryptSk<B: Backend> { + fn encrypt_sk<DataSkGLWE, DataSkLWE>( + &mut self, + module: &Module<B>, + sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>, + sk_lwe: &LWESecret<DataSkLWE>, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + DataSkGLWE: DataRef, + DataSkLWE: DataRef; +} + +#[derive(Clone)] +pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> { + pub(crate) keys: Vec<GGSWCiphertext<D>>, + pub(crate) dist: Distribution, + pub(crate) _phantom: PhantomData<BRT>, +} + +impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKey<D, BRT> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: Data, BRT: BlindRotationAlgo> PartialEq for BlindRotationKey<D, BRT> { + fn eq(&self, other: &Self) -> bool { + if self.keys.len() != other.keys.len() { + return false; + } + for (a, b) in self.keys.iter().zip(other.keys.iter()) { + if a != b { + return false; + } + } + + self.dist == other.dist && self._phantom == other._phantom + } +} + +impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKey<D, BRT> {} + +impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKey<D, BRT> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, key) in self.keys.iter().enumerate() { + write!(f, "key[{}]: {}", i, key)?; + } + writeln!(f, "{:?}", self.dist) + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> Reset for BlindRotationKey<D, BRT> { + fn reset(&mut self) { + self.keys.iter_mut().for_each(|key| key.reset()); + self.dist = Distribution::NONE; + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKey<D, BRT> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key| key.fill_uniform(source)); + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> ReaderFrom for BlindRotationKey<D, BRT> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + match Distribution::read_from(reader) { + Ok(dist) => self.dist = dist, + Err(e) => return Err(e), + } + let len: usize = reader.read_u64::<LittleEndian>()? as usize; + if self.keys.len() != len { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("self.keys.len()={} != read len={}", self.keys.len(), len), + )); + } + for key in &mut self.keys { + key.read_from(reader)?; + } + Ok(()) + } +} + +impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKey<D, BRT> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + match self.dist.write_to(writer) { + Ok(()) => {} + Err(e) => return Err(e), + } + writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +} + +impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKey<D, BRT> { + #[allow(dead_code)] + pub(crate) fn n(&self) -> usize { + self.keys[0].n() + } + + #[allow(dead_code)] + pub(crate) fn rows(&self) -> usize { + self.keys[0].rows() + } + + #[allow(dead_code)] + pub(crate) fn k(&self) -> usize { + self.keys[0].k() + } + + #[allow(dead_code)] + pub(crate) fn size(&self) -> usize { + self.keys[0].size() + } + + #[allow(dead_code)] + pub(crate) fn rank(&self) -> usize { + self.keys[0].rank() + } + + pub(crate) fn basek(&self) -> usize { + self.keys[0].basek() + } + + #[allow(dead_code)] + pub(crate) fn block_size(&self) -> usize { + match self.dist { + Distribution::BinaryBlock(value) => value, + _ => 1, + } + } +}
@@ -0,0 +1,141 @@
+use backend::hal::{ + api::{FillUniform, Reset}, + layouts::{Data, DataMut, DataRef, ReaderFrom, WriterTo}, +}; + +use std::{fmt, marker::PhantomData}; + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use core::{ + Distribution, + layouts::{Infos, compressed::GGSWCiphertextCompressed}, +}; + +use crate::tfhe::blind_rotation::BlindRotationAlgo; + +#[derive(Clone)] +pub struct BlindRotationKeyCompressed<D: Data, BRT: BlindRotationAlgo> { + pub(crate) keys: Vec<GGSWCiphertextCompressed<D>>, + pub(crate) dist: Distribution, + pub(crate) _phantom: PhantomData<BRT>, +} + +impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKeyCompressed<D, BRT> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl<D: Data, BRT: BlindRotationAlgo> PartialEq for BlindRotationKeyCompressed<D, BRT> { + fn eq(&self, other: &Self) -> bool { + if self.keys.len() != other.keys.len() { + return false; + } + for (a, b) in self.keys.iter().zip(other.keys.iter()) { + if a != b { + return false; + } + } + self.dist == other.dist && self._phantom == other._phantom + } +} + +impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKeyCompressed<D, BRT> {} + +impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKeyCompressed<D, BRT> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, key) in self.keys.iter().enumerate() { + write!(f, "key[{}]: {}", i, key)?; + } + writeln!(f, "{:?}", self.dist) + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> Reset for BlindRotationKeyCompressed<D, BRT> { + fn reset(&mut self) { + self.keys.iter_mut().for_each(|key| key.reset()); + self.dist = Distribution::NONE; + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKeyCompressed<D, BRT> { + fn fill_uniform(&mut self, source: &mut sampling::source::Source) { + self.keys + .iter_mut() + .for_each(|key| key.fill_uniform(source)); + } +} + +impl<D: DataMut, BRT: BlindRotationAlgo> ReaderFrom for BlindRotationKeyCompressed<D, BRT> { + fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { + match Distribution::read_from(reader) { + Ok(dist) => self.dist = dist, + Err(e) => return Err(e), + } + let len: usize = reader.read_u64::<LittleEndian>()? as usize; + if self.keys.len() != len { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("self.keys.len()={} != read len={}", self.keys.len(), len), + )); + } + for key in &mut self.keys { + key.read_from(reader)?; + } + Ok(()) + } +} + +impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKeyCompressed<D, BRT> { + fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { + match self.dist.write_to(writer) { + Ok(()) => {} + Err(e) => return Err(e), + } + writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; + for key in &self.keys { + key.write_to(writer)?; + } + Ok(()) + } +} + +impl<D: DataRef, BRA: BlindRotationAlgo> BlindRotationKeyCompressed<D, BRA> { + #[allow(dead_code)] + pub(crate) fn n(&self) -> usize { + self.keys[0].n() + } + + #[allow(dead_code)] + pub(crate) fn rows(&self) -> usize { + self.keys[0].rows() + } + + #[allow(dead_code)] + pub(crate) fn k(&self) -> usize { + self.keys[0].k() + } + + #[allow(dead_code)] + pub(crate) fn size(&self) -> usize { + self.keys[0].size() + } + + #[allow(dead_code)] + pub(crate) fn rank(&self) -> usize { + self.keys[0].rank() + } + + #[allow(dead_code)] + pub(crate) fn basek(&self) -> usize { + self.keys[0].basek() + } + + #[allow(dead_code)] + pub(crate) fn block_size(&self) -> usize { + match self.dist { + Distribution::BinaryBlock(value) => value, + _ => 1, + } + } +}
@@ -0,0 +1,125 @@
+use backend::hal::{ + api::{SvpPPolAlloc, SvpPrepare, VmpPMatAlloc, VmpPMatPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, ScalarZnx, Scratch, SvpPPol}, +}; + +use std::marker::PhantomData; + +use core::{ + Distribution, + layouts::{ + Infos, + prepared::{GGSWCiphertextPrepared, Prepare, PrepareAlloc}, + }, +}; + +use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, utils::set_xai_plus_y}; + +pub trait BlindRotationKeyPreparedAlloc<B: Backend> { + fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self; +} + +#[derive(PartialEq, Eq)] +pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend> { + pub(crate) data: Vec<GGSWCiphertextPrepared<D, B>>, + pub(crate) dist: Distribution, + pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>, + pub(crate) _phantom: PhantomData<BRT>, +} + +impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyPrepared<D, BRT, B> { + #[allow(dead_code)] + pub(crate) fn n(&self) -> usize { + self.data[0].n() + } + + #[allow(dead_code)] + pub(crate) fn rows(&self) -> usize { + self.data[0].rows() + } + + #[allow(dead_code)] + pub(crate) fn k(&self) -> usize { + self.data[0].k() + } + + #[allow(dead_code)] + pub(crate) fn size(&self) -> usize { + self.data[0].size() + } + + #[allow(dead_code)] + pub(crate) fn rank(&self) -> usize { + self.data[0].rank() + } + + pub(crate) fn basek(&self) -> usize { + self.data[0].basek() + } + + pub(crate) fn block_size(&self) -> usize { + match self.dist { + Distribution::BinaryBlock(value) => value, + _ => 1, + } + } +} + +impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>> + for BlindRotationKey<D, BRA> +where + BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlindRotationKeyPreparedAlloc<B>, + BlindRotationKeyPrepared<Vec<u8>, BRA, B>: Prepare<B, BlindRotationKey<D, BRA>>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> BlindRotationKeyPrepared<Vec<u8>, BRA, B> { + let mut brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = BlindRotationKeyPrepared::alloc( + module, + self.n(), + self.keys.len(), + self.basek(), + self.k(), + self.rows(), + self.rank(), + ); + brk.prepare(module, self, scratch); + brk + } +} + +impl<DM: DataMut, DR: DataRef, BRA: BlindRotationAlgo, B: Backend> Prepare<B, BlindRotationKey<DR, BRA>> + for BlindRotationKeyPrepared<DM, BRA, B> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B> + SvpPPolAlloc<B> + SvpPrepare<B>, +{ + fn prepare(&mut self, module: &Module<B>, other: &BlindRotationKey<DR, BRA>, scratch: &mut Scratch<B>) { + #[cfg(debug_assertions)] + { + assert_eq!(self.data.len(), other.keys.len()); + } + + let n: usize = other.n(); + + self.data + .iter_mut() + .zip(other.keys.iter()) + .for_each(|(ggsw_prepared, other)| { + ggsw_prepared.prepare(module, other, scratch); + }); + + self.dist = other.dist; + + match other.dist { + Distribution::BinaryBlock(_) => { + let mut x_pow_a: Vec<SvpPPol<Vec<u8>, B>> = Vec::with_capacity(n << 1); + let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); + (0..n << 1).for_each(|i| { + let mut res: SvpPPol<Vec<u8>, B> = module.svp_ppol_alloc(n, 1); + set_xai_plus_y(module, i, 0, &mut res, &mut buf); + x_pow_a.push(res); + }); + self.x_pow_a = Some(x_pow_a); + } + _ => {} + } + } +}
@@ -0,0 +1,35 @@
+mod cggi_algo; +mod cggi_key; +mod key; +mod key_compressed; +mod key_prepared; +mod lut; +mod utils; + +pub use cggi_algo::*; +pub use key::*; +pub use key_compressed::*; +pub use key_prepared::*; +pub use lut::*; + +pub mod tests; + +use backend::hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; +use core::layouts::{GLWECiphertext, LWECiphertext}; + +pub trait BlindRotationAlgo {} + +#[derive(Clone)] +pub struct CGGI {} +impl BlindRotationAlgo for CGGI {} + +pub trait BlincRotationExecute<B: Backend> { + fn execute<DR: DataMut, DI: DataRef>( + &self, + module: &Module<B>, + res: &mut GLWECiphertext<DR>, + lwe: &LWECiphertext<DI>, + lut: &LookUpTable, + scratch: &mut Scratch<B>, + ); +}
@@ -0,0 +1,160 @@
+use backend::hal::{ + api::{ + ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxFillUniform, VecZnxRotateInplace, + VecZnxSub, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, ZnxView, + }, + layouts::{Backend, Module, ScratchOwned}, + oep::{ + ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, + TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl, + }, +}; +use sampling::source::Source; + +use crate::tfhe::blind_rotation::{ + BlincRotationExecute, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared, + CCGIBlindRotationFamily, CGGI, LookUpTable, cggi_blind_rotate_scratch_space, mod_switch_2n, +}; + +use core::{ + layouts::{ + GLWECiphertext, GLWEPlaintext, GLWESecret, Infos, LWECiphertext, LWECiphertextToRef, LWEPlaintext, LWESecret, + prepared::{GLWESecretPrepared, PrepareAlloc}, + }, + trait_families::{GLWEDecryptFamily, GLWESecretPreparedModuleFamily}, +}; + +pub fn test_blind_rotation<B: Backend>(module: &Module<B>, n_lwe: usize, block_size: usize, extension_factor: usize) +where + Module<B>: CCGIBlindRotationFamily<B> + + GLWESecretPreparedModuleFamily<B> + + GLWEDecryptFamily<B> + + VecZnxFillUniform + + VecZnxAddNormal + + VecZnxAddScalarInplace + + VecZnxRotateInplace + + VecZnxSwithcDegree + + VecZnxSub + + VmpPMatAlloc<B> + + VmpPMatPrepare<B>, + B: VecZnxDftAllocBytesImpl<B> + + VecZnxBigAllocBytesImpl<B> + + ScratchOwnedAllocImpl<B> + + ScratchOwnedBorrowImpl<B> + + TakeVecZnxDftImpl<B> + + TakeVecZnxBigImpl<B> + + TakeVecZnxDftSliceImpl<B> + + ScratchAvailableImpl<B> + + TakeVecZnxImpl<B> + + TakeVecZnxSliceImpl<B>, +{ + let n: usize = module.n(); + let basek: usize = 19; + let k_lwe: usize = 24; + let k_brk: usize = 3 * basek; + let rows_brk: usize = 2; // Ensures first limb is noise-free. + let k_lut: usize = 1 * basek; + let k_res: usize = 2 * basek; + let rank: usize = 1; + + let message_modulus: usize = 1 << 4; + + let mut source_xs: Source = Source::new([2u8; 32]); + let mut source_xe: Source = Source::new([2u8; 32]); + let mut source_xa: Source = Source::new([1u8; 32]); + + let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKey::generate_from_sk_scratch_space( + module, n, basek, k_brk, rank, + )); + + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank); + sk_glwe.fill_ternary_prob(0.5, &mut source_xs); + let sk_glwe_dft: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); + + let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe); + sk_lwe.fill_binary_block(block_size, &mut source_xs); + + let mut scratch_br: ScratchOwned<B> = ScratchOwned::<B>::alloc(cggi_blind_rotate_scratch_space( + module, + n, + block_size, + extension_factor, + basek, + k_res, + k_brk, + rows_brk, + rank, + )); + + let mut brk: BlindRotationKey<Vec<u8>, CGGI> = + BlindRotationKey::<Vec<u8>, CGGI>::alloc(n, n_lwe, basek, k_brk, rows_brk, rank); + + brk.encrypt_sk( + module, + &sk_glwe_dft, + &sk_lwe, + &mut source_xa, + &mut source_xe, + 3.2, + scratch.borrow(), + ); + + let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe, basek, k_lwe); + + let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe); + + let x: i64 = 2; + let bits: usize = 8; + + pt_lwe.encode_i64(x, bits); + + lwe.encrypt_sk( + module, + &pt_lwe, + &sk_lwe, + &mut source_xa, + &mut source_xe, + 3.2, + ); + + let mut f: Vec<i64> = vec![0i64; message_modulus]; + f.iter_mut() + .enumerate() + .for_each(|(i, x)| *x = 2 * (i as i64) + 1); + + let mut lut: LookUpTable = LookUpTable::alloc(n, basek, k_lut, extension_factor); + lut.set(module, &f, message_modulus); + + let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_res, rank); + + let brk_prepared: BlindRotationKeyPrepared<Vec<u8>, CGGI, B> = brk.prepare_alloc(module, scratch.borrow()); + + brk_prepared.execute(module, &mut res, &lwe, &lut, scratch_br.borrow()); + + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_res); + + res.decrypt(module, &mut pt_have, &sk_glwe_dft, scratch.borrow()); + + let mut lwe_2n: Vec<i64> = vec![0i64; lwe.n() + 1]; // TODO: from scratch space + + mod_switch_2n( + 2 * lut.domain_size(), + &mut lwe_2n, + &lwe.to_ref(), + lut.rotation_direction(), + ); + + let pt_want: i64 = (lwe_2n[0] + + lwe_2n[1..] + .iter() + .zip(sk_lwe.raw()) + .map(|(x, y)| x * y) + .sum::<i64>()) + & (2 * lut.domain_size() - 1) as i64; + + lut.rotate(module, pt_want); + + // First limb should be exactly equal (test are parameterized such that the noise does not reach + // the first limb) + assert_eq!(pt_have.data.at(0, 0), lut.data[0].at(0, 0)); +}
@@ -0,0 +1,15 @@
+use backend::hal::tests::serialization::test_reader_writer_interface; + +use crate::tfhe::blind_rotation::{BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, CGGI}; + +#[test] +fn test_cggi_blind_rotation_key_serialization() { + let original: BlindRotationKey<Vec<u8>, CGGI> = BlindRotationKey::alloc(256, 64, 12, 54, 2, 2); + test_reader_writer_interface(original); +} + +#[test] +fn test_cggi_blind_rotation_key_compressed_serialization() { + let original: BlindRotationKeyCompressed<Vec<u8>, CGGI> = BlindRotationKeyCompressed::alloc(256, 64, 12, 54, 2, 2); + test_reader_writer_interface(original); +}
@@ -0,0 +1,7 @@
+#[cfg(test)] +mod generic_serialization; +#[cfg(test)] +mod implementation; + +pub mod generic_blind_rotation; +pub mod generic_lut;
@@ -0,0 +1,41 @@
+use backend::hal::{ + api::{SvpPrepare, ZnxInfos, ZnxViewMut}, + layouts::{Backend, DataMut, Module, ScalarZnx, SvpPPol}, +}; + +pub(crate) fn set_xai_plus_y<A, C, B: Backend>( + module: &Module<B>, + ai: usize, + y: i64, + res: &mut SvpPPol<A, B>, + buf: &mut ScalarZnx<C>, +) where + A: DataMut, + C: DataMut, + Module<B>: SvpPrepare<B>, +{ + let n: usize = res.n(); + + { + let raw: &mut [i64] = buf.at_mut(0, 0); + if ai < n { + raw[ai] = 1; + } else { + raw[(ai - n) & (n - 1)] = -1; + } + raw[0] += y; + } + + module.svp_prepare(res, 0, buf, 0); + + { + let raw: &mut [i64] = buf.at_mut(0, 0); + + if ai < n { + raw[ai] = 0; + } else { + raw[(ai - n) & (n - 1)] = 0; + } + raw[0] = 0; + } +}
@@ -0,0 +1,397 @@
+use std::{collections::HashMap, time::Instant, usize}; + +use backend::hal::{ + api::{ + ScratchAvailable, TakeMatZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, TakeVecZnxSlice, + VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAutomorphismInplace, VecZnxBigSubSmallBInplace, VecZnxCopy, + VecZnxDftCopy, VecZnxDftToVecZnxBigTmpA, VecZnxNegateInplace, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, + VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, + }, + layouts::{Backend, DataMut, DataRef, Module, Scratch}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, +}; + +use core::{GLWEOperations, TakeGGLWE, TakeGLWECt, layouts::Infos, trait_families::GLWETraceModuleFamily}; + +use core::layouts::{GGSWCiphertext, GLWECiphertext, LWECiphertext, prepared::GGLWEAutomorphismKeyPrepared}; + +use crate::tfhe::{ + blind_rotation::{ + BlincRotationExecute, BlindRotationAlgo, BlindRotationKeyPrepared, CCGIBlindRotationFamily, LookUpTable, + LookUpTableRotationDirection, + }, + circuit_bootstrapping::{CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute}, +}; + +pub trait CircuitBootstrapFamily<B: Backend> = VecZnxRotateInplace + + VecZnxNormalizeInplace<B> + + VecZnxNormalizeTmpBytes + + CCGIBlindRotationFamily<B> + + VecZnxSwithcDegree + + VecZnxBigAutomorphismInplace<B> + + VecZnxRshInplace + + VecZnxDftCopy<B> + + VecZnxDftToVecZnxBigTmpA<B> + + VecZnxSub + + VecZnxAddInplace + + VecZnxNegateInplace + + VecZnxCopy + + VecZnxSubABInplace + + GLWETraceModuleFamily<B> + + VecZnxRotateInplace + + VecZnxAutomorphismInplace + + VecZnxBigSubSmallBInplace<B>; + +impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> CirtuitBootstrappingExecute<B> for CircuitBootstrappingKeyPrepared<D, BRA, B> +where + Module<B>: CircuitBootstrapFamily<B>, + B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + Scratch<B>: TakeVecZnx + + TakeVecZnxDftSlice<B> + + TakeVecZnxBig<B> + + TakeVecZnxDft<B> + + TakeMatZnx + + ScratchAvailable + + TakeVecZnxSlice, + BlindRotationKeyPrepared<D, BRA, B>: BlincRotationExecute<B>, +{ + fn execute_to_constant<DM: DataMut, DR: DataRef>( + &self, + module: &Module<B>, + res: &mut GGSWCiphertext<DM>, + lwe: &LWECiphertext<DR>, + log_domain: usize, + extension_factor: usize, + scratch: &mut Scratch<B>, + ) { + circuit_bootstrap_core( + false, + module, + 0, + res, + lwe, + log_domain, + extension_factor, + self, + scratch, + ); + } + + fn execute_to_exponent<DM: DataMut, DR: DataRef>( + &self, + module: &Module<B>, + log_gap_out: usize, + res: &mut GGSWCiphertext<DM>, + lwe: &LWECiphertext<DR>, + log_domain: usize, + extension_factor: usize, + scratch: &mut Scratch<B>, + ) { + circuit_bootstrap_core( + true, + module, + log_gap_out, + res, + lwe, + log_domain, + extension_factor, + self, + scratch, + ); + } +} + +pub fn circuit_bootstrap_core<DRes, DLwe, DBrk, BRA: BlindRotationAlgo, B: Backend>( + to_exponent: bool, + module: &Module<B>, + log_gap_out: usize, + res: &mut GGSWCiphertext<DRes>, + lwe: &LWECiphertext<DLwe>, + log_domain: usize, + extension_factor: usize, + key: &CircuitBootstrappingKeyPrepared<DBrk, BRA, B>, + scratch: &mut Scratch<B>, +) where + DRes: DataMut, + DLwe: DataRef, + DBrk: DataRef, + Module<B>: CircuitBootstrapFamily<B>, + B: ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + Scratch<B>: TakeVecZnxDftSlice<B> + + TakeVecZnxBig<B> + + TakeVecZnxDft<B> + + TakeVecZnx + + ScratchAvailable + + TakeVecZnxSlice + + TakeMatZnx, + BlindRotationKeyPrepared<DBrk, BRA, B>: BlincRotationExecute<B>, +{ + #[cfg(debug_assertions)] + { + assert_eq!(res.n(), key.brk.n()); + assert_eq!(lwe.basek(), key.brk.basek()); + assert_eq!(res.basek(), key.brk.basek()); + } + + let n: usize = res.n(); + let basek: usize = res.basek(); + let rows: usize = res.rows(); + let rank: usize = res.rank(); + let k: usize = res.k(); + + let alpha: usize = rows.next_power_of_two(); + + let mut f: Vec<i64> = vec![0i64; (1 << log_domain) * alpha]; + + if to_exponent { + (0..rows).for_each(|i| { + f[i] = 1 << (basek * (rows - 1 - i)); + }); + } else { + (0..1 << log_domain).for_each(|j| { + (0..rows).for_each(|i| { + f[j * alpha + i] = j as i64 * (1 << (basek * (rows - 1 - i))); + }); + }); + } + + // Lut precision, basically must be able to hold the decomposition power basis of the GGSW + let mut lut: LookUpTable = LookUpTable::alloc(n, basek, basek * rows, extension_factor); + lut.set(module, &f, basek * rows); + + if to_exponent { + lut.set_rotation_direction(LookUpTableRotationDirection::Right); + } + + // TODO: separate GGSW k from output of blind rotation k + let (mut res_glwe, scratch1) = scratch.take_glwe_ct(n, basek, k, rank); + let (mut tmp_gglwe, scratch2) = scratch1.take_gglwe(n, basek, k, rows, 1, rank, rank); + + let now: Instant = Instant::now(); + + key.brk.execute(module, &mut res_glwe, &lwe, &lut, scratch2); + + println!("blind_rotate: {} ms", now.elapsed().as_millis()); + + let gap: usize = 2 * lut.drift / lut.extension_factor(); + + let log_gap_in: usize = (usize::BITS - (gap * alpha - 1).leading_zeros()) as _; + + (0..rows).for_each(|i| { + let mut tmp_glwe: GLWECiphertext<&mut [u8]> = tmp_gglwe.at_mut(i, 0); + + if to_exponent { + let now: Instant = Instant::now(); + + // Isolates i-th LUT and moves coefficients according to requested gap. + post_process( + module, + &mut tmp_glwe, + &res_glwe, + log_gap_in, + log_gap_out, + log_domain, + &key.atk, + scratch2, + ); + println!("post_process: {} ms", now.elapsed().as_millis()); + } else { + tmp_glwe.trace(module, 0, module.log_n(), &res_glwe, &key.atk, scratch2); + } + + if i < rows { + res_glwe.rotate_inplace(module, -(gap as i64)); + } + }); + + // Expands GGLWE to GGSW using GGLWE(s^2) + res.from_gglwe(module, &tmp_gglwe, &key.tsk, scratch2); +} + +fn post_process<DataRes, DataA, B: Backend>( + module: &Module<B>, + res: &mut GLWECiphertext<DataRes>, + a: &GLWECiphertext<DataA>, + log_gap_in: usize, + log_gap_out: usize, + log_domain: usize, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, + scratch: &mut Scratch<B>, +) where + DataRes: DataMut, + DataA: DataRef, + Module<B>: CircuitBootstrapFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +{ + let log_n: usize = module.log_n(); + + let mut cts: HashMap<usize, GLWECiphertext<Vec<u8>>> = HashMap::new(); + + // First partial trace, vanishes all coefficients which are not multiples of gap_in + // [1, 1, 1, 1, 0, 0, 0, ..., 0, 0, -1, -1, -1, -1] -> [1, 0, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0] + res.trace( + module, + module.log_n() - log_gap_in as usize + 1, + log_n, + &a, + auto_keys, + scratch, + ); + + // TODO: optimize with packing and final partial trace + // If gap_out < gap_in, then we need to repack, i.e. reduce the cap between coefficients. + if log_gap_in != log_gap_out { + let steps: i32 = 1 << log_domain; + (0..steps).for_each(|i| { + if i != 0 { + res.rotate_inplace(module, -(1 << log_gap_in)); + } + cts.insert(i as usize * (1 << log_gap_out), res.clone()); + }); + + let now: Instant = Instant::now(); + pack(module, &mut cts, log_gap_out, auto_keys, scratch); + println!("pack: {} ms", now.elapsed().as_millis()); + let packed: GLWECiphertext<Vec<u8>> = cts.remove(&0).unwrap(); + res.trace( + module, + log_n - log_gap_out, + log_n, + &packed, + auto_keys, + scratch, + ); + } +} + +pub fn pack<D: DataMut, B: Backend>( + module: &Module<B>, + cts: &mut HashMap<usize, GLWECiphertext<D>>, + log_gap_out: usize, + auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, + scratch: &mut Scratch<B>, +) where + Module<B>: CircuitBootstrapFamily<B>, + Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, +{ + let log_n: usize = module.log_n(); + + let basek: usize = cts.get(&0).unwrap().basek(); + let k: usize = cts.get(&0).unwrap().k(); + let rank: usize = cts.get(&0).unwrap().rank(); + + (0..log_n - log_gap_out).for_each(|i| { + let now: Instant = Instant::now(); + + let t = 16.min(1 << (log_n - 1 - i)); + + let auto_key: &GGLWEAutomorphismKeyPrepared<Vec<u8>, B>; + if i == 0 { + auto_key = auto_keys.get(&-1).unwrap() + } else { + auto_key = auto_keys.get(&module.galois_element(1 << (i - 1))).unwrap(); + } + + (0..t).for_each(|j| { + let mut a: Option<GLWECiphertext<D>> = cts.remove(&j); + let mut b: Option<GLWECiphertext<D>> = cts.remove(&(j + t)); + + combine( + module, + basek, + k, + rank, + a.as_mut(), + b.as_mut(), + i, + auto_key, + scratch, + ); + + if let Some(a) = a { + cts.insert(j, a); + } else if let Some(b) = b { + cts.insert(j, b); + } + }); + + println!("combine: {} us", now.elapsed().as_micros()); + }); +} + +fn combine<A: DataMut, D: DataMut, DataAK: DataRef, B: Backend>( + module: &Module<B>, + basek: usize, + k: usize, + rank: usize, + a: Option<&mut GLWECiphertext<A>>, + b: Option<&mut GLWECiphertext<D>>, + i: usize, + auto_key: &GGLWEAutomorphismKeyPrepared<DataAK, B>, + scratch: &mut Scratch<B>, +) where + Module<B>: CircuitBootstrapFamily<B>, + Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, +{ + // Goal is to evaluate: a = a + b*X^t + phi(a - b*X^t)) + // We also use the identity: AUTO(a * X^t, g) = -X^t * AUTO(a, g) + // where t = 2^(log_n - i - 1) and g = 5^{2^(i - 1)} + // Different cases for wether a and/or b are zero. + // + // Implicite RSH without modulus switch, introduces extra I(X) * Q/2 on decryption. + // Necessary so that the scaling of the plaintext remains constant. + // It however is ok to do so here because coefficients are eventually + // either mapped to garbage or twice their value which vanishes I(X) + // since 2*(I(X) * Q/2) = I(X) * Q = 0 mod Q. + if let Some(a) = a { + let n: usize = a.n(); + let log_n: usize = (u64::BITS - (n - 1).leading_zeros()) as _; + let t: i64 = 1 << (log_n - i - 1); + + if let Some(b) = b { + let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(n, basek, k, rank); + + // a = a * X^-t + a.rotate_inplace(module, -t); + + // tmp_b = a * X^-t - b + tmp_b.sub(module, a, b); + tmp_b.rsh(module, 1); + + // a = a * X^-t + b + a.add_inplace(module, b); + a.rsh(module, 1); + + tmp_b.normalize_inplace(module, scratch_1); + + // tmp_b = phi(a * X^-t - b) + tmp_b.automorphism_inplace(module, auto_key, scratch_1); + + // a = a * X^-t + b - phi(a * X^-t - b) + a.sub_inplace_ab(module, &tmp_b); + a.normalize_inplace(module, scratch_1); + + // a = a + b * X^t - phi(a * X^-t - b) * X^t + // = a + b * X^t - phi(a * X^-t - b) * - phi(X^t) + // = a + b * X^t + phi(a - b * X^t) + a.rotate_inplace(module, t); + } else { + a.rsh(module, 1); + // a = a + phi(a) + a.automorphism_add_inplace(module, auto_key, scratch); + } + } else { + if let Some(b) = b { + let n: usize = b.n(); + let log_n: usize = (u64::BITS - (n - 1).leading_zeros()) as _; + let t: i64 = 1 << (log_n - i - 1); + + let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(n, basek, k, rank); + tmp_b.rotate(module, t, b); + tmp_b.rsh(module, 1); + + // a = (b* X^t - phi(b* X^t)) + b.automorphism_sub_ba(module, &tmp_b, auto_key, scratch_1); + } + } +}
@@ -0,0 +1,150 @@
+use core::layouts::{ + GGLWEAutomorphismKey, GGLWETensorKey, GLWECiphertext, GLWESecret, LWESecret, + prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc}, +}; +use std::{collections::HashMap, usize}; + +use backend::hal::{ + api::{ + ScratchAvailable, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddScalarInplace, + VecZnxAutomorphism, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare, + }, + layouts::{Backend, Data, DataRef, Module, Scratch}, +}; +use sampling::source::Source; + +use core::trait_families::{ + GGLWEAutomorphismKeyEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GGSWEncryptSkFamily, GLWESecretPreparedModuleFamily, +}; + +use crate::tfhe::blind_rotation::{ + BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared, +}; + +pub trait CircuitBootstrappingKeyEncryptSk<B: Backend> { + fn encrypt_sk<DLwe, DGlwe>( + module: &Module<B>, + basek: usize, + sk_lwe: &LWESecret<DLwe>, + sk_glwe: &GLWESecret<DGlwe>, + k_brk: usize, + rows_brk: usize, + k_trace: usize, + rows_trace: usize, + k_tsk: usize, + rows_tsk: usize, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) -> Self + where + DLwe: DataRef, + DGlwe: DataRef; +} + +pub struct CircuitBootstrappingKey<D: Data, BRA: BlindRotationAlgo> { + pub(crate) brk: BlindRotationKey<D, BRA>, + pub(crate) tsk: GGLWETensorKey<Vec<u8>>, + pub(crate) atk: HashMap<i64, GGLWEAutomorphismKey<Vec<u8>>>, +} + +impl<BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyEncryptSk<B> for CircuitBootstrappingKey<Vec<u8>, BRA> +where + BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>, + Module<B>: GGSWEncryptSkFamily<B> + + GLWESecretPreparedModuleFamily<B> + + VecZnxAddScalarInplace + + GGLWEAutomorphismKeyEncryptSkFamily<B> + + VecZnxAutomorphism + + VecZnxSwithcDegree + + GGLWETensorKeyEncryptSkFamily<B>, + Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<B> + TakeVecZnxBig<B>, +{ + fn encrypt_sk<DLwe, DGlwe>( + module: &Module<B>, + basek: usize, + sk_lwe: &LWESecret<DLwe>, + sk_glwe: &GLWESecret<DGlwe>, + k_brk: usize, + rows_brk: usize, + k_trace: usize, + rows_trace: usize, + k_tsk: usize, + rows_tsk: usize, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) -> Self + where + DLwe: DataRef, + DGlwe: DataRef, + { + let mut auto_keys: HashMap<i64, GGLWEAutomorphismKey<Vec<u8>>> = HashMap::new(); + let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(&module); + gal_els.iter().for_each(|gal_el| { + let mut key: GGLWEAutomorphismKey<Vec<u8>> = + GGLWEAutomorphismKey::alloc(sk_glwe.n(), basek, k_trace, rows_trace, 1, sk_glwe.rank()); + key.encrypt_sk( + &module, *gal_el, &sk_glwe, source_xa, source_xe, sigma, scratch, + ); + auto_keys.insert(*gal_el, key); + }); + + let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch); + + let mut brk: BlindRotationKey<Vec<u8>, BRA> = BlindRotationKey::<Vec<u8>, BRA>::alloc( + sk_glwe.n(), + sk_lwe.n(), + basek, + k_brk, + rows_brk, + sk_glwe.rank(), + ); + + brk.encrypt_sk( + module, + &sk_glwe_prepared, + sk_lwe, + source_xa, + source_xe, + sigma, + scratch, + ); + + let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(sk_glwe.n(), basek, k_tsk, rows_tsk, 1, sk_glwe.rank()); + tsk.encrypt_sk(module, &sk_glwe, source_xa, source_xe, sigma, scratch); + + Self { + brk, + atk: auto_keys, + tsk, + } + } +} + +pub struct CircuitBootstrappingKeyPrepared<D: Data, BRA: BlindRotationAlgo, B: Backend> { + pub(crate) brk: BlindRotationKeyPrepared<D, BRA, B>, + pub(crate) tsk: GGLWETensorKeyPrepared<Vec<u8>, B>, + pub(crate) atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, +} + +impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B>> + for CircuitBootstrappingKey<D, BRA> +where + Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>, + BlindRotationKey<D, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>, + GGLWETensorKey<D>: PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>>, + GGLWEAutomorphismKey<D>: PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, +{ + fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> { + let brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = self.brk.prepare_alloc(module, scratch); + let tsk: GGLWETensorKeyPrepared<Vec<u8>, B> = self.tsk.prepare_alloc(module, scratch); + let mut atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); + for (key, value) in &self.atk { + atk.insert(*key, value.prepare_alloc(module, scratch)); + } + CircuitBootstrappingKeyPrepared { brk, tsk, atk } + } +}
@@ -0,0 +1,33 @@
+mod circuit_bootstrapping; +mod key; +pub mod tests; + +pub use circuit_bootstrapping::*; +pub use key::*; + +use core::layouts::{GGSWCiphertext, LWECiphertext}; + +use backend::hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; + +pub trait CirtuitBootstrappingExecute<B: Backend> { + fn execute_to_constant<DM: DataMut, DR: DataRef>( + &self, + module: &Module<B>, + res: &mut GGSWCiphertext<DM>, + lwe: &LWECiphertext<DR>, + log_domain: usize, + extension_factor: usize, + scratch: &mut Scratch<B>, + ); + + fn execute_to_exponent<DM: DataMut, DR: DataRef>( + &self, + module: &Module<B>, + log_gap_out: usize, + res: &mut GGSWCiphertext<DM>, + lwe: &LWECiphertext<DR>, + log_domain: usize, + extension_factor: usize, + scratch: &mut Scratch<B>, + ); +}
@@ -0,0 +1,23 @@
+use backend::{ + hal::{api::ModuleNew, layouts::Module}, + implementation::cpu_spqlios::FFT64, +}; + +use crate::tfhe::{ + blind_rotation::CGGI, + circuit_bootstrapping::tests::circuit_bootstrapping::{ + test_circuit_bootstrapping_to_constant, test_circuit_bootstrapping_to_exponent, + }, +}; + +#[test] +fn test_to_constant() { + let module: Module<FFT64> = Module::<FFT64>::new(256); + test_circuit_bootstrapping_to_constant::<FFT64, CGGI>(&module); +} + +#[test] +fn test_to_exponent() { + let module: Module<FFT64> = Module::<FFT64>::new(256); + test_circuit_bootstrapping_to_exponent::<FFT64, CGGI>(&module); +}
@@ -0,0 +1,1 @@
+mod fft64;
@@ -0,0 +1,1 @@
+mod cpu_spqlios;
@@ -0,0 +1,4 @@
+pub mod circuit_bootstrapping; + +#[cfg(test)] +mod implementation;