diff --git a/Makefile b/Makefile index 179bb5420..055bd6a0d 100644 --- a/Makefile +++ b/Makefile @@ -1489,7 +1489,7 @@ parse_wasm_benchmarks: install_rs_check_toolchain .PHONY: write_params_to_file # Gather all crypto parameters into a file with a Sage readable format. write_params_to_file: install_rs_check_toolchain RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) run \ - --example write_params_to_file --features=boolean,shortint,internal-keycache + --example write_params_to_file --features=boolean,shortint,hpu,internal-keycache .PHONY: clone_backward_compat_data # Clone the data repo needed for backward compatibility tests clone_backward_compat_data: diff --git a/tfhe/Cargo.toml b/tfhe/Cargo.toml index a7632d54e..b0f9af560 100644 --- a/tfhe/Cargo.toml +++ b/tfhe/Cargo.toml @@ -184,7 +184,7 @@ required-features = ["boolean"] [[example]] name = "write_params_to_file" path = "examples/utilities/params_to_file.rs" -required-features = ["boolean", "shortint", "internal-keycache"] +required-features = ["boolean", "shortint", "internal-keycache", "hpu"] [[example]] name = "print_doc_bench_parameters" diff --git a/tfhe/examples/utilities/params_to_file.rs b/tfhe/examples/utilities/params_to_file.rs index 640992a8e..8fa1b9fa9 100644 --- a/tfhe/examples/utilities/params_to_file.rs +++ b/tfhe/examples/utilities/params_to_file.rs @@ -4,17 +4,50 @@ use std::io::Write; use std::path::Path; use tfhe::boolean::parameters::{BooleanParameters, VEC_BOOLEAN_PARAM}; use tfhe::core_crypto::commons::parameters::{GlweDimension, LweDimension, PolynomialSize}; -use tfhe::core_crypto::prelude::{DynamicDistribution, TUniform, UnsignedInteger}; +use tfhe::core_crypto::prelude::{ + CiphertextModulus, DynamicDistribution, TUniform, UnsignedInteger, +}; use tfhe::keycache::NamedParam; use tfhe::shortint::parameters::current_params::{ VEC_ALL_CLASSIC_PBS_PARAMETERS, VEC_ALL_COMPACT_PUBLIC_KEY_ENCRYPTION_PARAMETERS, - VEC_ALL_COMPRESSION_PARAMETERS, VEC_ALL_MULTI_BIT_PBS_PARAMETERS, - VEC_ALL_NOISE_SQUASHING_PARAMETERS, + VEC_ALL_COMPRESSION_PARAMETERS, VEC_ALL_HPU_PARAMETERS, VEC_ALL_KS32_PARAMETERS, + VEC_ALL_MULTI_BIT_PBS_PARAMETERS, VEC_ALL_NOISE_SQUASHING_PARAMETERS, }; use tfhe::shortint::parameters::{ CompactPublicKeyEncryptionParameters, CompressionParameters, NoiseSquashingParameters, - ShortintParameterSet, }; +use tfhe::shortint::AtomicPatternParameters; + +#[derive(Debug, Eq, PartialEq, Hash)] +pub enum ParamModulus { + NativeU128, + Other(u128), +} +impl ParamModulus { + fn from_ciphertext_modulus( + ct_modulus: CiphertextModulus, + ) -> Self { + let scalar_bits = ct_modulus.associated_scalar_bits(); + assert!(scalar_bits <= 128, "ciphertext modulus is too large"); + + if ct_modulus.is_native_modulus() { + if scalar_bits == 128 { + ParamModulus::NativeU128 + } else { + ParamModulus::Other(1u128.checked_shl(scalar_bits as u32).unwrap()) + } + } else { + ParamModulus::Other(ct_modulus.get_custom_modulus()) + } + } + + fn as_f64(&self) -> f64 { + match self { + Self::NativeU128 => 2.0_f64.powi(128), + Self::Other(u) => *u as f64, + } + } +} pub trait ParamDetails { fn lwe_dimension(&self) -> LweDimension; @@ -22,7 +55,8 @@ pub trait ParamDetails { fn lwe_noise_distribution(&self) -> DynamicDistribution; fn glwe_noise_distribution(&self) -> DynamicDistribution; fn polynomial_size(&self) -> PolynomialSize; - fn log_ciphertext_modulus(&self) -> usize; + fn lwe_ciphertext_modulus(&self) -> ParamModulus; + fn glwe_ciphertext_modulus(&self) -> ParamModulus; } impl ParamDetails for BooleanParameters { @@ -45,12 +79,16 @@ impl ParamDetails for BooleanParameters { self.polynomial_size } - fn log_ciphertext_modulus(&self) -> usize { - 32 + fn lwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::Other(1u128.checked_shl(u32::BITS).unwrap()) + } + + fn glwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::Other(1u128.checked_shl(u32::BITS).unwrap()) } } -impl ParamDetails for ShortintParameterSet { +impl ParamDetails for AtomicPatternParameters { fn lwe_dimension(&self) -> LweDimension { self.lwe_dimension() } @@ -70,9 +108,17 @@ impl ParamDetails for ShortintParameterSet { self.polynomial_size() } - fn log_ciphertext_modulus(&self) -> usize { - assert!(self.ciphertext_modulus().is_native_modulus()); - 64 + fn lwe_ciphertext_modulus(&self) -> ParamModulus { + match self { + Self::Standard(p) => ParamModulus::from_ciphertext_modulus(p.ciphertext_modulus()), + Self::KeySwitch32(p) => { + ParamModulus::from_ciphertext_modulus(p.post_keyswitch_ciphertext_modulus) + } + } + } + + fn glwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::from_ciphertext_modulus(self.ciphertext_modulus()) } } @@ -98,9 +144,14 @@ impl ParamDetails for CompactPublicKeyEncryptionParameters { panic!("polynomial_size not applicable for compact public-key encryption parameters") } - fn log_ciphertext_modulus(&self) -> usize { - assert!(self.ciphertext_modulus.is_native_modulus()); - 64 + fn lwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::from_ciphertext_modulus(self.ciphertext_modulus) + } + + fn glwe_ciphertext_modulus(&self) -> ParamModulus { + panic!( + "glwe_ciphertext_modulus not applicable for compact public-key encryption parameters" + ) } } @@ -124,8 +175,12 @@ impl ParamDetails for CompressionParameters { self.packing_ks_polynomial_size } - fn log_ciphertext_modulus(&self) -> usize { - 64 + fn lwe_ciphertext_modulus(&self) -> ParamModulus { + panic!("lwe_ciphertext_modulus not applicable for compression parameters") + } + + fn glwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::from_ciphertext_modulus(CiphertextModulus::::new_native()) } } @@ -150,9 +205,12 @@ impl ParamDetails for NoiseSquashingParameters { self.polynomial_size } - fn log_ciphertext_modulus(&self) -> usize { - assert!(self.ciphertext_modulus.is_native_modulus()); - u128::BITS as usize + fn lwe_ciphertext_modulus(&self) -> ParamModulus { + panic!("lwe_ciphertext_modulus not applicable for NoiseSquashingParameters") + } + + fn glwe_ciphertext_modulus(&self) -> ParamModulus { + ParamModulus::from_ciphertext_modulus(self.ciphertext_modulus) } } @@ -164,27 +222,26 @@ enum ParametersFormat { } type NoiseDistributionString = String; -type LogCiphertextModulus = usize; #[derive(Eq, PartialEq, Hash)] struct ParamGroupKey { lwe_dimension: LweDimension, - log_ciphertext_modulus: LogCiphertextModulus, + ciphertext_modulus: ParamModulus, noise_distribution: NoiseDistributionString, // TODO might not need to be hashed since LWE and GLWE share the same security check parameters_format: ParametersFormat, } -fn format_modulus_as_string(log_ciphertext_modulus: usize) -> String { - if log_ciphertext_modulus > 128 { - panic!("Exponent too large"); +fn format_modulus_as_string(modulus: ParamModulus) -> String { + match modulus { + ParamModulus::NativeU128 => { + // What are you gonna do, call the police ? + "340282366920938463463374607431768211456".to_string() + } + ParamModulus::Other(u) => { + format!("{u}") + } } - if log_ciphertext_modulus == 128 { - // What are you gonna do, call the police ? - return "340282366920938463463374607431768211456".to_string(); - } - - format!("{}", 1u128 << log_ciphertext_modulus) } ///Function to print in the lattice_estimator format the parameters @@ -197,14 +254,14 @@ pub fn format_lwe_parameters_to_lattice_estimator { let modular_std_dev = - param.log_ciphertext_modulus() as f64 + distrib.standard_dev().0.log2(); + (param.lwe_ciphertext_modulus().as_f64() * distrib.standard_dev().0).log2(); format!( "{}_LWE = LWE.Parameters(\n n = {},\n q ={},\n Xs=ND.Uniform(0,1), \n \ Xe=ND.DiscreteGaussian({}),\n tag=('{}_lwe',) \n)\n\n", name, param.lwe_dimension().0, - format_modulus_as_string(param.log_ciphertext_modulus()), + format_modulus_as_string(param.lwe_ciphertext_modulus()), 2.0_f64.powf(modular_std_dev), similar_params.join("_lwe', '") ) @@ -215,7 +272,7 @@ pub fn format_lwe_parameters_to_lattice_estimator { let modular_std_dev = - param.log_ciphertext_modulus() as f64 + distrib.standard_dev().0.log2(); + (param.glwe_ciphertext_modulus().as_f64() * distrib.standard_dev().0).log2(); format!( "{}_GLWE = LWE.Parameters(\n n = {},\n q = {},\n Xs=ND.Uniform(0,1), \n \ @@ -243,7 +300,7 @@ pub fn format_glwe_parameters_to_lattice_estimator + Copy + Name ParametersFormat::LweGlwe => vec![ ParamGroupKey { lwe_dimension: params.lwe_dimension(), - log_ciphertext_modulus: params.log_ciphertext_modulus(), + ciphertext_modulus: params.lwe_ciphertext_modulus(), noise_distribution: params.lwe_noise_distribution().to_string(), parameters_format: ParametersFormat::Lwe, }, @@ -302,14 +359,14 @@ fn write_all_params_in_file + Copy + Name lwe_dimension: params .glwe_dimension() .to_equivalent_lwe_dimension(params.polynomial_size()), - log_ciphertext_modulus: params.log_ciphertext_modulus(), + ciphertext_modulus: params.glwe_ciphertext_modulus(), noise_distribution: params.glwe_noise_distribution().to_string(), parameters_format: ParametersFormat::Glwe, }, ], ParametersFormat::Lwe => vec![ParamGroupKey { lwe_dimension: params.lwe_dimension(), - log_ciphertext_modulus: params.log_ciphertext_modulus(), + ciphertext_modulus: params.lwe_ciphertext_modulus(), noise_distribution: params.lwe_noise_distribution().to_string(), parameters_format: ParametersFormat::Lwe, }], @@ -317,7 +374,7 @@ fn write_all_params_in_file + Copy + Name lwe_dimension: params .glwe_dimension() .to_equivalent_lwe_dimension(params.polynomial_size()), - log_ciphertext_modulus: params.log_ciphertext_modulus(), + ciphertext_modulus: params.glwe_ciphertext_modulus(), noise_distribution: params.glwe_noise_distribution().to_string(), parameters_format: ParametersFormat::Glwe, }], @@ -388,7 +445,7 @@ fn main() { let classic_pbs: Vec<_> = VEC_ALL_CLASSIC_PBS_PARAMETERS .into_iter() - .map(|p| (ShortintParameterSet::from(*p.0), Some(p.1))) + .map(|p| (AtomicPatternParameters::from(*p.0), Some(p.1))) .collect(); write_all_params_in_file( "shortint_classic_parameters_lattice_estimator.sage", @@ -398,7 +455,7 @@ fn main() { let multi_bit_pbs: Vec<_> = VEC_ALL_MULTI_BIT_PBS_PARAMETERS .into_iter() - .map(|p| (ShortintParameterSet::from(*p.0), Some(p.1))) + .map(|p| (AtomicPatternParameters::from(*p.0), Some(p.1))) .collect(); write_all_params_in_file( "shortint_multi_bit_parameters_lattice_estimator.sage", @@ -436,13 +493,23 @@ fn main() { ParametersFormat::Glwe, ); - // TODO perform this gathering later - // let wopbs = ALL_PARAMETER_VEC_WOPBS - // .iter() - // .map(|p| ShortintParameterSet::from(*p)) - // .collect::>(); - // write_all_params_in_file( - // "shortint_wopbs_parameters_lattice_estimator.sage", - // &wopbs, - // ); + let ks32_params: Vec<_> = VEC_ALL_KS32_PARAMETERS + .into_iter() + .map(|p| (AtomicPatternParameters::from(*p.0), Some(p.1))) + .collect(); + write_all_params_in_file( + "shortint_ks32_parameters_lattice_estimator.sage", + &ks32_params, + ParametersFormat::LweGlwe, + ); + + let hpu_params: Vec<_> = VEC_ALL_HPU_PARAMETERS + .into_iter() + .map(|p| (AtomicPatternParameters::from(*p.0), Some(p.1))) + .collect(); + write_all_params_in_file( + "shortint_hpu_parameters_lattice_estimator.sage", + &hpu_params, + ParametersFormat::LweGlwe, + ); } diff --git a/tfhe/src/core_crypto/commons/ciphertext_modulus.rs b/tfhe/src/core_crypto/commons/ciphertext_modulus.rs index fde597844..87008b135 100644 --- a/tfhe/src/core_crypto/commons/ciphertext_modulus.rs +++ b/tfhe/src/core_crypto/commons/ciphertext_modulus.rs @@ -363,6 +363,10 @@ impl CiphertextModulus { CiphertextModulusInner::Custom(non_zero) => non_zero.get() as f64, } } + + pub const fn associated_scalar_bits(&self) -> usize { + Scalar::BITS + } } impl From> for CiphertextModulusLog { diff --git a/tfhe/src/shortint/keycache.rs b/tfhe/src/shortint/keycache.rs index 6fdd9f419..a19f9f0ac 100644 --- a/tfhe/src/shortint/keycache.rs +++ b/tfhe/src/shortint/keycache.rs @@ -444,6 +444,12 @@ impl NamedParam for AtomicPatternParameters { } } +impl NamedParam for KeySwitch32PBSParameters { + fn name(&self) -> String { + ShortintParameterSet::from(*self).name() + } +} + named_params_impl!(ShortintKeySwitchingParameters => V1_2_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128, ; fallback => ks_params_default_name diff --git a/tfhe/src/shortint/parameters/v1_2/mod.rs b/tfhe/src/shortint/parameters/v1_2/mod.rs index 1f460dc4e..bd44dd4c8 100644 --- a/tfhe/src/shortint/parameters/v1_2/mod.rs +++ b/tfhe/src/shortint/parameters/v1_2/mod.rs @@ -45,7 +45,8 @@ pub use hpu::*; use crate::shortint::parameters::{ ClassicPBSParameters, CompactPublicKeyEncryptionParameters, CompressionParameters, - MultiBitPBSParameters, NoiseSquashingParameters, ShortintKeySwitchingParameters, + KeySwitch32PBSParameters, MultiBitPBSParameters, NoiseSquashingParameters, + ShortintKeySwitchingParameters, }; /// All [`ClassicPBSParameters`] in this module. @@ -1693,5 +1694,22 @@ pub const VEC_ALL_NOISE_SQUASHING_PARAMETERS: [(&NoiseSquashingParameters, &str) "V1_2_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128", )]; +pub const VEC_ALL_KS32_PARAMETERS: [(&KeySwitch32PBSParameters, &str); 1] = [( + &V1_2_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128, + "V1_2_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128", +)]; + #[cfg(feature = "hpu")] pub mod hpu; + +#[cfg(feature = "hpu")] +pub const VEC_ALL_HPU_PARAMETERS: [(&KeySwitch32PBSParameters, &str); 2] = [ + ( + &V1_2_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_GAUSSIAN_2M64, + "V1_2_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_GAUSSIAN_2M64", + ), + ( + &V1_2_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M64, + "V1_2_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M64", + ), +]; diff --git a/tfhe/src/shortint/parameters/v1_3/mod.rs b/tfhe/src/shortint/parameters/v1_3/mod.rs index 584b9891e..a20bccd3c 100644 --- a/tfhe/src/shortint/parameters/v1_3/mod.rs +++ b/tfhe/src/shortint/parameters/v1_3/mod.rs @@ -45,7 +45,8 @@ pub use hpu::*; use crate::shortint::parameters::{ ClassicPBSParameters, CompactPublicKeyEncryptionParameters, CompressionParameters, - MultiBitPBSParameters, NoiseSquashingParameters, ShortintKeySwitchingParameters, + KeySwitch32PBSParameters, MultiBitPBSParameters, NoiseSquashingParameters, + ShortintKeySwitchingParameters, }; /// All [`ClassicPBSParameters`] in this module. @@ -1693,5 +1694,22 @@ pub const VEC_ALL_NOISE_SQUASHING_PARAMETERS: [(&NoiseSquashingParameters, &str) "V1_3_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128", )]; +pub const VEC_ALL_KS32_PARAMETERS: [(&KeySwitch32PBSParameters, &str); 1] = [( + &V1_3_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128, + "V1_3_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128", +)]; + #[cfg(feature = "hpu")] pub mod hpu; + +#[cfg(feature = "hpu")] +pub const VEC_ALL_HPU_PARAMETERS: [(&KeySwitch32PBSParameters, &str); 2] = [ + ( + &V1_3_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_GAUSSIAN_2M64, + "V1_3_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_GAUSSIAN_2M64", + ), + ( + &V1_3_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M64, + "V1_3_HPU_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M64", + ), +];