mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 15:18:33 -05:00
test: add multi bit blind rotate traits
- given the nature of the mod switch it seems easier to think in terms of mod switch + blind rotate, the classic PBS might get updated in a similar way, to be determined
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
use crate::core_crypto::commons::dispersion::Variance;
|
||||
use crate::core_crypto::commons::noise_formulas::lwe_multi_bit_programmable_bootstrap::{
|
||||
multi_bit_pbs_variance_132_bits_security_gaussian_gf_2_fft_mul,
|
||||
multi_bit_pbs_variance_132_bits_security_gaussian_gf_3_fft_mul,
|
||||
multi_bit_pbs_variance_132_bits_security_gaussian_gf_4_fft_mul,
|
||||
multi_bit_pbs_variance_132_bits_security_tuniform_gf_2_fft_mul,
|
||||
multi_bit_pbs_variance_132_bits_security_tuniform_gf_3_fft_mul,
|
||||
multi_bit_pbs_variance_132_bits_security_tuniform_gf_4_fft_mul,
|
||||
};
|
||||
use crate::core_crypto::commons::noise_formulas::noise_simulation::traits::LweMultiBitFftBlindRotate;
|
||||
use crate::core_crypto::commons::noise_formulas::noise_simulation::{
|
||||
NoiseSimulationGlwe, NoiseSimulationLwe, NoiseSimulationModulus,
|
||||
};
|
||||
use crate::core_crypto::commons::parameters::{
|
||||
DecompositionBaseLog, DecompositionLevelCount, DynamicDistribution, GlweSize,
|
||||
LweBskGroupingFactor, LweDimension, PolynomialSize,
|
||||
};
|
||||
use crate::core_crypto::commons::traits::container::Container;
|
||||
use crate::core_crypto::entities::lwe_multi_bit_bootstrap_key::FourierLweMultiBitBootstrapKey;
|
||||
use crate::core_crypto::fft_impl::fft64::c64;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct NoiseSimulationLweMultiBitFourierBsk {
|
||||
input_lwe_dimension: LweDimension,
|
||||
output_glwe_size: GlweSize,
|
||||
output_polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
grouping_factor: LweBskGroupingFactor,
|
||||
noise_distribution: DynamicDistribution<u64>,
|
||||
modulus: NoiseSimulationModulus,
|
||||
}
|
||||
|
||||
impl NoiseSimulationLweMultiBitFourierBsk {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
input_lwe_dimension: LweDimension,
|
||||
output_glwe_size: GlweSize,
|
||||
output_polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
grouping_factor: LweBskGroupingFactor,
|
||||
noise_distribution: DynamicDistribution<u64>,
|
||||
modulus: NoiseSimulationModulus,
|
||||
) -> Self {
|
||||
Self {
|
||||
input_lwe_dimension,
|
||||
output_glwe_size,
|
||||
output_polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
grouping_factor,
|
||||
noise_distribution,
|
||||
modulus,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matches_actual_bsk<C: Container<Element = c64>>(
|
||||
&self,
|
||||
lwe_bsk: &FourierLweMultiBitBootstrapKey<C>,
|
||||
) -> bool {
|
||||
let Self {
|
||||
input_lwe_dimension,
|
||||
output_glwe_size: glwe_size,
|
||||
output_polynomial_size: polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
grouping_factor,
|
||||
noise_distribution: _,
|
||||
modulus: _,
|
||||
} = *self;
|
||||
|
||||
let bsk_input_lwe_dimension = lwe_bsk.input_lwe_dimension();
|
||||
let bsk_glwe_size = lwe_bsk.glwe_size();
|
||||
let bsk_polynomial_size = lwe_bsk.polynomial_size();
|
||||
let bsk_decomp_base_log = lwe_bsk.decomposition_base_log();
|
||||
let bsk_decomp_level_count = lwe_bsk.decomposition_level_count();
|
||||
let bsk_grouping_factor = lwe_bsk.grouping_factor();
|
||||
|
||||
input_lwe_dimension == bsk_input_lwe_dimension
|
||||
&& glwe_size == bsk_glwe_size
|
||||
&& polynomial_size == bsk_polynomial_size
|
||||
&& decomp_base_log == bsk_decomp_base_log
|
||||
&& decomp_level_count == bsk_decomp_level_count
|
||||
&& grouping_factor == bsk_grouping_factor
|
||||
}
|
||||
|
||||
pub fn input_lwe_dimension(&self) -> LweDimension {
|
||||
self.input_lwe_dimension
|
||||
}
|
||||
|
||||
pub fn output_glwe_size(&self) -> GlweSize {
|
||||
self.output_glwe_size
|
||||
}
|
||||
|
||||
pub fn output_polynomial_size(&self) -> PolynomialSize {
|
||||
self.output_polynomial_size
|
||||
}
|
||||
|
||||
pub fn decomp_base_log(&self) -> DecompositionBaseLog {
|
||||
self.decomp_base_log
|
||||
}
|
||||
|
||||
pub fn decomp_level_count(&self) -> DecompositionLevelCount {
|
||||
self.decomp_level_count
|
||||
}
|
||||
|
||||
pub fn grouping_factor(&self) -> LweBskGroupingFactor {
|
||||
self.grouping_factor
|
||||
}
|
||||
|
||||
pub fn noise_distribution(&self) -> DynamicDistribution<u64> {
|
||||
self.noise_distribution
|
||||
}
|
||||
|
||||
pub fn modulus(&self) -> NoiseSimulationModulus {
|
||||
self.modulus
|
||||
}
|
||||
}
|
||||
|
||||
impl LweMultiBitFftBlindRotate<NoiseSimulationLwe, NoiseSimulationLwe, NoiseSimulationGlwe>
|
||||
for NoiseSimulationLweMultiBitFourierBsk
|
||||
{
|
||||
type SideResources = ();
|
||||
|
||||
fn lwe_multi_bit_fft_blind_rotate(
|
||||
&self,
|
||||
input: &NoiseSimulationLwe,
|
||||
output: &mut NoiseSimulationLwe,
|
||||
accumulator: &NoiseSimulationGlwe,
|
||||
_side_resources: &mut Self::SideResources,
|
||||
) {
|
||||
assert_eq!(self.input_lwe_dimension(), input.lwe_dimension());
|
||||
assert_eq!(
|
||||
self.output_glwe_size(),
|
||||
accumulator.glwe_dimension().to_glwe_size()
|
||||
);
|
||||
assert_eq!(self.output_polynomial_size(), accumulator.polynomial_size());
|
||||
assert_eq!(self.modulus(), accumulator.modulus());
|
||||
let grouping_factor = self.grouping_factor();
|
||||
|
||||
let br_additive_variance = match self.noise_distribution() {
|
||||
DynamicDistribution::Gaussian(_) => match grouping_factor.0 {
|
||||
2 => multi_bit_pbs_variance_132_bits_security_gaussian_gf_2_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
3 => multi_bit_pbs_variance_132_bits_security_gaussian_gf_3_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
4 => multi_bit_pbs_variance_132_bits_security_gaussian_gf_4_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
gf => panic!("Unsupported grouping factor: {gf}"),
|
||||
},
|
||||
DynamicDistribution::TUniform(_) => match grouping_factor.0 {
|
||||
2 => multi_bit_pbs_variance_132_bits_security_tuniform_gf_2_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
3 => multi_bit_pbs_variance_132_bits_security_tuniform_gf_3_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
4 => multi_bit_pbs_variance_132_bits_security_tuniform_gf_4_fft_mul(
|
||||
self.input_lwe_dimension(),
|
||||
self.output_glwe_size().to_glwe_dimension(),
|
||||
self.output_polynomial_size(),
|
||||
self.decomp_base_log(),
|
||||
self.decomp_level_count(),
|
||||
self.modulus().as_f64(),
|
||||
),
|
||||
gf => panic!("Unsupported grouping factor: {gf}"),
|
||||
},
|
||||
};
|
||||
|
||||
let output_lwe_dimension = self
|
||||
.output_glwe_size()
|
||||
.to_glwe_dimension()
|
||||
.to_equivalent_lwe_dimension(self.output_polynomial_size());
|
||||
|
||||
*output = NoiseSimulationLwe::new(
|
||||
output_lwe_dimension,
|
||||
Variance(accumulator.variance_per_occupied_slot().0 + br_additive_variance.0),
|
||||
accumulator.modulus,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod lwe_keyswitch;
|
||||
pub mod lwe_multi_bit_programmable_bootstrap;
|
||||
pub mod lwe_packing_keyswitch;
|
||||
pub mod lwe_programmable_bootstrap;
|
||||
pub mod modulus_switch;
|
||||
@@ -13,7 +14,7 @@ pub use lwe_programmable_bootstrap::{
|
||||
use crate::core_crypto::commons::ciphertext_modulus::CiphertextModulus;
|
||||
use crate::core_crypto::commons::dispersion::Variance;
|
||||
use crate::core_crypto::commons::noise_formulas::noise_simulation::traits::{
|
||||
AllocateLweBootstrapResult, ScalarMul, ScalarMulAssign,
|
||||
AllocateLweBootstrapResult, AllocateLweMultiBitBlindRotateResult, ScalarMul, ScalarMulAssign,
|
||||
};
|
||||
use crate::core_crypto::commons::numeric::{CastInto, UnsignedInteger};
|
||||
use crate::core_crypto::commons::parameters::{
|
||||
@@ -192,3 +193,23 @@ impl AllocateLweBootstrapResult for NoiseSimulationGlwe {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AllocateLweMultiBitBlindRotateResult for NoiseSimulationGlwe {
|
||||
type Output = NoiseSimulationLwe;
|
||||
type SideResources = ();
|
||||
|
||||
fn allocate_lwe_multi_bit_blind_rotate_result(
|
||||
&self,
|
||||
_side_resources: &mut Self::SideResources,
|
||||
) -> Self::Output {
|
||||
let lwe_dimension = self
|
||||
.glwe_dimension()
|
||||
.to_equivalent_lwe_dimension(self.polynomial_size());
|
||||
|
||||
Self::Output {
|
||||
lwe_dimension,
|
||||
variance: self.variance_per_occupied_slot(),
|
||||
modulus: self.modulus(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
pub trait AllocateLweMultiBitBlindRotateResult {
|
||||
type Output;
|
||||
type SideResources;
|
||||
|
||||
fn allocate_lwe_multi_bit_blind_rotate_result(
|
||||
&self,
|
||||
side_resources: &mut Self::SideResources,
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
||||
pub trait LweMultiBitFftBlindRotate<Input, Output, Accumulator> {
|
||||
type SideResources;
|
||||
|
||||
fn lwe_multi_bit_fft_blind_rotate(
|
||||
&self,
|
||||
input: &Input,
|
||||
output: &mut Output,
|
||||
accumulator: &Accumulator,
|
||||
side_resources: &mut Self::SideResources,
|
||||
);
|
||||
}
|
||||
|
||||
pub trait LweMultiBitFft128BlindRotate<Input, Output, Accumulator> {
|
||||
type SideResources;
|
||||
|
||||
fn lwe_multi_bit_fft_128_blind_rotate(
|
||||
&self,
|
||||
input: &Input,
|
||||
output: &mut Output,
|
||||
accumulator: &Accumulator,
|
||||
side_resources: &mut Self::SideResources,
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
pub mod lwe_keyswitch;
|
||||
pub mod lwe_multi_bit_programmable_bootstrap;
|
||||
pub mod lwe_packing_keyswitch;
|
||||
pub mod lwe_programmable_bootstrap;
|
||||
pub mod modulus_switch;
|
||||
pub mod scalar_mul;
|
||||
|
||||
pub use lwe_keyswitch::{AllocateLweKeyswitchResult, LweKeyswitch};
|
||||
pub use lwe_multi_bit_programmable_bootstrap::{
|
||||
AllocateLweMultiBitBlindRotateResult, LweMultiBitFft128BlindRotate, LweMultiBitFftBlindRotate,
|
||||
};
|
||||
pub use lwe_packing_keyswitch::{AllocateLwePackingKeyswitchResult, LwePackingKeyswitch};
|
||||
pub use lwe_programmable_bootstrap::{
|
||||
AllocateLweBootstrapResult, LweClassicFft128Bootstrap, LweClassicFftBootstrap,
|
||||
|
||||
Reference in New Issue
Block a user