mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 07:08:03 -05:00
refactor(tfhe): add GGSW encryption with coherency test between old and new
This commit is contained in:
224
tfhe/src/core_crypto/algorithms/ggsw_encryption.rs
Normal file
224
tfhe/src/core_crypto/algorithms/ggsw_encryption.rs
Normal file
@@ -0,0 +1,224 @@
|
||||
use crate::core_crypto::algorithms::slice_algorithms::*;
|
||||
use crate::core_crypto::algorithms::*;
|
||||
use crate::core_crypto::commons::crypto::secret::generators::EncryptionRandomGenerator;
|
||||
use crate::core_crypto::commons::math::decomposition::DecompositionLevel;
|
||||
use crate::core_crypto::commons::math::random::ByteRandomGenerator;
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::dispersion::DispersionParameter;
|
||||
|
||||
pub fn encrypt_ggsw_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
|
||||
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
|
||||
output: &mut GgswCiphertextBase<OutputCont>,
|
||||
encoded: Plaintext<Scalar>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
Gen: ByteRandomGenerator,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
// ck_dim_eq!(self.key_size() => output.glwe_size().to_glwe_dimension());
|
||||
|
||||
assert!(
|
||||
output.polynomial_size() == glwe_secret_key.polynomial_size(),
|
||||
"Mismatch between polynomial sizes of output cipertexts and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
output.polynomial_size(),
|
||||
glwe_secret_key.polynomial_size()
|
||||
);
|
||||
|
||||
assert!(
|
||||
output.glwe_size().to_glwe_dimension() == glwe_secret_key.glwe_dimension(),
|
||||
"Mismatch between GlweDimension of output cipertexts and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
output.glwe_size().to_glwe_dimension(),
|
||||
glwe_secret_key.glwe_dimension()
|
||||
);
|
||||
|
||||
// Generators used to have same sequential and parallel key generation
|
||||
let gen_iter = generator
|
||||
.fork_ggsw_to_ggsw_levels::<Scalar>(
|
||||
output.decomposition_level_count(),
|
||||
output.glwe_size(),
|
||||
output.polynomial_size(),
|
||||
)
|
||||
.expect("Failed to split generator into ggsw levels");
|
||||
|
||||
let output_glwe_size = output.glwe_size();
|
||||
let output_polynomial_size = output.polynomial_size();
|
||||
let decomp_base_log = output.decomposition_base_log();
|
||||
|
||||
for (level_index, (mut level_matrix, mut generator)) in
|
||||
output.iter_mut().zip(gen_iter).enumerate()
|
||||
{
|
||||
let decomp_level = DecompositionLevel(level_index + 1);
|
||||
let factor = encoded
|
||||
.0
|
||||
.wrapping_neg()
|
||||
.wrapping_mul(Scalar::ONE << (Scalar::BITS - (decomp_base_log.0 * decomp_level.0)));
|
||||
|
||||
// We iterate over the rows of the level matrix, the last row needs special treatment
|
||||
let gen_iter = generator
|
||||
.fork_ggsw_level_to_glwe::<Scalar>(output_glwe_size, output_polynomial_size)
|
||||
.expect("Failed to split generator into glwe");
|
||||
|
||||
let last_row_index = level_matrix.glwe_size().0 - 1;
|
||||
let sk_poly_list = glwe_secret_key.as_polynomial_list();
|
||||
|
||||
for ((row_index, mut row_as_glwe), mut generator) in level_matrix
|
||||
.as_mut_glwe_list()
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.zip(gen_iter)
|
||||
{
|
||||
encrypt_ggsw_level_matrix_row(
|
||||
glwe_secret_key,
|
||||
(row_index, last_row_index),
|
||||
factor,
|
||||
&sk_poly_list,
|
||||
&mut row_as_glwe,
|
||||
noise_parameters,
|
||||
&mut generator,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn encrypt_ggsw_level_matrix_row<Scalar, KeyCont, InputCont, OutputCont, Gen>(
|
||||
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
|
||||
(row_index, last_row_index): (usize, usize),
|
||||
factor: Scalar,
|
||||
sk_poly_list: &PolynomialListBase<InputCont>,
|
||||
row_as_glwe: &mut GlweCiphertextBase<OutputCont>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
if row_index < last_row_index {
|
||||
// Not the last row
|
||||
let sk_poly = sk_poly_list.get(row_index);
|
||||
|
||||
// Copy the key polynomial to the output body, to avoid allocating a temporary buffer
|
||||
let mut body = row_as_glwe.get_mut_body();
|
||||
body.as_mut().copy_from_slice(sk_poly.as_ref());
|
||||
|
||||
update_with_wrapping_scalar_mul(body.as_mut(), factor);
|
||||
|
||||
encrypt_glwe_ciphertext_in_place(glwe_secret_key, row_as_glwe, noise_parameters, generator);
|
||||
} else {
|
||||
// The last row needs a slightly different treatment
|
||||
let mut body = row_as_glwe.get_mut_body();
|
||||
|
||||
body.as_mut().fill(Scalar::ZERO);
|
||||
body.as_mut()[0] = factor.wrapping_neg();
|
||||
|
||||
encrypt_glwe_ciphertext_in_place(glwe_secret_key, row_as_glwe, noise_parameters, generator);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::core_crypto::algorithms::encrypt_ggsw_ciphertext;
|
||||
use crate::core_crypto::commons::crypto::encoding::PlaintextList;
|
||||
use crate::core_crypto::commons::crypto::secret::generators::{
|
||||
DeterministicSeeder, EncryptionRandomGenerator,
|
||||
};
|
||||
use crate::core_crypto::commons::crypto::secret::GlweSecretKey;
|
||||
use crate::core_crypto::commons::math::random::Seeder;
|
||||
use crate::core_crypto::commons::math::tensor::*;
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
use crate::core_crypto::commons::test_tools;
|
||||
use crate::core_crypto::entities::{GgswCiphertext, GlweSecretKeyBase, Plaintext};
|
||||
use crate::core_crypto::prelude::{
|
||||
DecompositionBaseLog, DecompositionLevelCount, LogStandardDev,
|
||||
};
|
||||
use concrete_csprng::generators::SoftwareRandomGenerator;
|
||||
|
||||
use crate::core_crypto::commons::crypto::ggsw::StandardGgswCiphertext;
|
||||
|
||||
fn test_refactored_ggsw<T: UnsignedTorus>() {
|
||||
// random settings
|
||||
let nb_ct = test_tools::random_ciphertext_count(10);
|
||||
let dimension = test_tools::random_glwe_dimension(5);
|
||||
let polynomial_size = test_tools::random_polynomial_size(200);
|
||||
let noise_parameters = LogStandardDev::from_log_standard_dev(-50.);
|
||||
let decomp_level = DecompositionLevelCount(3);
|
||||
let decomp_base_log = DecompositionBaseLog(7);
|
||||
let mut secret_generator = test_tools::new_secret_random_generator();
|
||||
|
||||
// generates a secret key
|
||||
let sk = GlweSecretKey::generate_binary(dimension, polynomial_size, &mut secret_generator);
|
||||
|
||||
// generates random plaintexts
|
||||
let plaintext_vector =
|
||||
PlaintextList::from_tensor(secret_generator.random_uniform_tensor::<T>(nb_ct.0));
|
||||
|
||||
for plaintext in plaintext_vector.plaintext_iter() {
|
||||
let main_seed = test_tools::random_seed();
|
||||
|
||||
// Use a deterministic seeder to get the seeds that will be used during the tests
|
||||
let mut deterministic_seeder =
|
||||
DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed);
|
||||
let _ = deterministic_seeder.seed();
|
||||
let mask_seed = deterministic_seeder.seed();
|
||||
|
||||
let mut generator = EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(
|
||||
mask_seed,
|
||||
&mut DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed),
|
||||
);
|
||||
|
||||
let mut refactored_ggsw = GgswCiphertext::new(
|
||||
T::ZERO,
|
||||
dimension.to_glwe_size(),
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level,
|
||||
);
|
||||
|
||||
encrypt_ggsw_ciphertext(
|
||||
&GlweSecretKeyBase::from_container(sk.as_tensor().as_slice(), polynomial_size),
|
||||
&mut refactored_ggsw,
|
||||
Plaintext(plaintext.0),
|
||||
noise_parameters,
|
||||
&mut generator,
|
||||
);
|
||||
|
||||
// control encryption
|
||||
let mut ggsw = StandardGgswCiphertext::allocate(
|
||||
T::ZERO,
|
||||
polynomial_size,
|
||||
dimension.to_glwe_size(),
|
||||
decomp_level,
|
||||
decomp_base_log,
|
||||
);
|
||||
|
||||
// Recreate a generator with the known mask seed
|
||||
let mut generator = EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(
|
||||
mask_seed,
|
||||
&mut DeterministicSeeder::<SoftwareRandomGenerator>::new(main_seed),
|
||||
);
|
||||
|
||||
sk.encrypt_constant_ggsw(&mut ggsw, plaintext, noise_parameters, &mut generator);
|
||||
|
||||
assert_eq!(refactored_ggsw.as_ref(), ggsw.as_tensor().as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_refactored_ggsw_u32() {
|
||||
test_refactored_ggsw::<u32>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_refactored_ggsw_u64() {
|
||||
test_refactored_ggsw::<u64>()
|
||||
}
|
||||
}
|
||||
46
tfhe/src/core_crypto/algorithms/glwe_encryption.rs
Normal file
46
tfhe/src/core_crypto/algorithms/glwe_encryption.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::core_crypto::algorithms::polynomial_algorithms::*;
|
||||
use crate::core_crypto::commons::crypto::secret::generators::EncryptionRandomGenerator;
|
||||
use crate::core_crypto::commons::math::random::ByteRandomGenerator;
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::dispersion::DispersionParameter;
|
||||
|
||||
pub fn encrypt_glwe_ciphertext_in_place<Scalar, KeyCont, OutputCont, Gen>(
|
||||
glwe_secret_key: &GlweSecretKeyBase<KeyCont>,
|
||||
output: &mut GlweCiphertextBase<OutputCont>,
|
||||
noise_parameters: impl DispersionParameter,
|
||||
generator: &mut EncryptionRandomGenerator<Gen>,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
output.glwe_size().to_glwe_dimension() == glwe_secret_key.glwe_dimension(),
|
||||
"Mismatch between GlweDimension of output cipertext and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
output.glwe_size().to_glwe_dimension(),
|
||||
glwe_secret_key.glwe_dimension()
|
||||
);
|
||||
assert!(
|
||||
output.polynomial_size() == glwe_secret_key.polynomial_size(),
|
||||
"Mismatch between PolynomialSize of output cipertext and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
output.polynomial_size(),
|
||||
glwe_secret_key.polynomial_size()
|
||||
);
|
||||
|
||||
let (mut mask, mut body) = output.get_mut_mask_and_body();
|
||||
|
||||
generator.fill_slice_with_random_mask(mask.as_mut());
|
||||
|
||||
generator.update_slice_with_wrapping_add_random_noise(body.as_mut(), noise_parameters);
|
||||
|
||||
update_polynomial_with_wrapping_add_multisum(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ use crate::core_crypto::commons::math::random::{
|
||||
use crate::core_crypto::commons::numeric::Numeric;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub fn allocate_and_generate_new_binary_glwe_secret_key<Scalar, Gen>(
|
||||
glwe_dimension: GlweDimension,
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::dispersion::DispersionParameter;
|
||||
use crate::core_crypto::specification::parameters::LweSize;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
|
||||
lwe_secret_key: &LweSecretKeyBase<KeyCont>,
|
||||
@@ -22,6 +22,14 @@ pub fn encrypt_lwe_ciphertext<Scalar, KeyCont, OutputCont, Gen>(
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
Gen: ByteRandomGenerator,
|
||||
{
|
||||
assert!(
|
||||
output.lwe_size().to_lwe_dimension() == lwe_secret_key.lwe_dimension(),
|
||||
"Mismatch between LweDimension of output cipertext and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
output.lwe_size().to_lwe_dimension(),
|
||||
lwe_secret_key.lwe_dimension()
|
||||
);
|
||||
|
||||
let (mut mask, body) = output.get_mut_mask_and_body();
|
||||
|
||||
generator.fill_slice_with_random_mask(mask.as_mut());
|
||||
@@ -97,6 +105,14 @@ where
|
||||
KeyCont: Container<Element = Scalar>,
|
||||
InputCont: Container<Element = Scalar>,
|
||||
{
|
||||
assert!(
|
||||
lwe_ciphertext.lwe_size().to_lwe_dimension() == lwe_secret_key.lwe_dimension(),
|
||||
"Mismatch between LweDimension of output cipertext and input secret key. \
|
||||
Got {:?} in output, and {:?} in secret key.",
|
||||
lwe_ciphertext.lwe_size().to_lwe_dimension(),
|
||||
lwe_secret_key.lwe_dimension()
|
||||
);
|
||||
|
||||
let (mask, body) = lwe_ciphertext.get_mask_and_body();
|
||||
|
||||
Plaintext(
|
||||
|
||||
@@ -6,9 +6,7 @@ use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::dispersion::DispersionParameter;
|
||||
use crate::core_crypto::specification::parameters::{
|
||||
DecompositionBaseLog, DecompositionLevelCount, PlaintextCount,
|
||||
};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub fn generate_binary_binary_lwe_keyswitch_key<
|
||||
Scalar,
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn lwe_ciphertext_in_place_cleartext_multiplication<Scalar, InCont>(
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
update_with_scalar_wrapping_mul(lhs.as_mut(), rhs.0);
|
||||
update_with_wrapping_scalar_mul(lhs.as_mut(), rhs.0);
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_subtraction<Scalar, LhsCont, RhsCont>(
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::core_crypto::commons::math::random::{
|
||||
use crate::core_crypto::commons::numeric::Numeric;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::LweDimension;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub fn allocate_and_generate_new_binary_lwe_secret_key<Scalar, Gen>(
|
||||
lwe_dimension: LweDimension,
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
pub mod ggsw_encryption;
|
||||
pub mod glwe_encryption;
|
||||
pub mod glwe_secret_key_generation;
|
||||
pub mod lwe_ciphertext_keyswitch;
|
||||
pub mod lwe_encryption;
|
||||
pub mod lwe_keyswitch_key_generation;
|
||||
pub mod lwe_linear_algebra;
|
||||
pub mod lwe_secret_key_generation;
|
||||
pub mod polynomial_algorithms;
|
||||
pub mod slice_algorithms;
|
||||
|
||||
// No pub use for slice algorithms which would not interest higher level users
|
||||
// No pub use for slice and polynomial algorithms which would not interest higher level users
|
||||
// They can still be used via `use crate::core_crypto::algorithms::slice_algorithms::*;`
|
||||
pub use ggsw_encryption::*;
|
||||
pub use glwe_encryption::*;
|
||||
pub use glwe_secret_key_generation::*;
|
||||
pub use lwe_ciphertext_keyswitch::*;
|
||||
pub use lwe_encryption::*;
|
||||
|
||||
62
tfhe/src/core_crypto/algorithms/polynomial_algorithms.rs
Normal file
62
tfhe/src/core_crypto/algorithms/polynomial_algorithms.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
pub fn update_polynomial_with_wrapping_add_multisum<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut PolynomialBase<OutputCont>,
|
||||
poly_list_1: &PolynomialListBase<InputCont1>,
|
||||
poly_list_2: &PolynomialListBase<InputCont2>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
InputCont1: Container<Element = Scalar>,
|
||||
InputCont2: Container<Element = Scalar>,
|
||||
{
|
||||
for (poly_1, poly_2) in poly_list_1.iter().zip(poly_list_2.iter()) {
|
||||
update_polynomial_with_wrapping_add_mul(output, &poly_1, &poly_2);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_polynomial_with_wrapping_add_mul<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut PolynomialBase<OutputCont>,
|
||||
lhs: &PolynomialBase<InputCont1>,
|
||||
rhs: &PolynomialBase<InputCont2>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
OutputCont: ContainerMut<Element = Scalar>,
|
||||
InputCont1: Container<Element = Scalar>,
|
||||
InputCont2: Container<Element = Scalar>,
|
||||
{
|
||||
assert!(
|
||||
output.polynomial_size() == lhs.polynomial_size(),
|
||||
"Output polynomial size {:?} is not the same as input lhs polynomial {:?}.",
|
||||
output.polynomial_size(),
|
||||
lhs.polynomial_size(),
|
||||
);
|
||||
assert!(
|
||||
output.polynomial_size() == rhs.polynomial_size(),
|
||||
"Output polynomial size {:?} is not the same as input rhs polynomial {:?}.",
|
||||
output.polynomial_size(),
|
||||
rhs.polynomial_size(),
|
||||
);
|
||||
let degree = output.degree();
|
||||
let polynomial_size = output.polynomial_size();
|
||||
|
||||
for (lhs_degree, &lhs_coeff) in lhs.iter().enumerate() {
|
||||
for (rhs_degree, &rhs_coeff) in rhs.iter().enumerate() {
|
||||
let target_degree = lhs_degree + rhs_degree;
|
||||
if target_degree <= degree {
|
||||
let output_coefficient = &mut output.as_mut()[target_degree];
|
||||
|
||||
*output_coefficient =
|
||||
(*output_coefficient).wrapping_add(lhs_coeff.wrapping_mul(rhs_coeff));
|
||||
} else {
|
||||
let target_degree = target_degree % polynomial_size.0;
|
||||
let output_coefficient = &mut output.as_mut()[target_degree];
|
||||
|
||||
*output_coefficient =
|
||||
(*output_coefficient).wrapping_sub(lhs_coeff.wrapping_mul(rhs_coeff));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ where
|
||||
.for_each(|elt| *elt = (*elt).wrapping_neg());
|
||||
}
|
||||
|
||||
pub fn update_with_scalar_wrapping_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
|
||||
pub fn update_with_wrapping_scalar_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::core_crypto::commons::math::random::{
|
||||
ByteRandomGenerator, Gaussian, RandomGenerable, RandomGenerator, Seed, Seeder, Uniform,
|
||||
};
|
||||
use crate::core_crypto::commons::math::tensor::AsMutTensor;
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
|
||||
use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
use crate::core_crypto::prelude::{
|
||||
@@ -202,6 +203,22 @@ impl<G: ByteRandomGenerator> EncryptionRandomGenerator<G> {
|
||||
self.noise
|
||||
.fill_tensor_with_random_gaussian(output, 0., std.get_standard_dev());
|
||||
}
|
||||
|
||||
// Adds noise on top of existing data for in place encryption
|
||||
pub(crate) fn update_slice_with_wrapping_add_random_noise<Scalar>(
|
||||
&mut self,
|
||||
output: &mut [Scalar],
|
||||
std: impl DispersionParameter,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
(Scalar, Scalar): RandomGenerable<Gaussian<f64>>,
|
||||
{
|
||||
self.noise.update_slice_with_wrapping_add_random_gaussian(
|
||||
output,
|
||||
0.,
|
||||
std.get_standard_dev(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "__commons_parallel")]
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::core_crypto::commons::math::random::{
|
||||
UniformWithZeros,
|
||||
};
|
||||
use crate::core_crypto::commons::math::tensor::{AsMutSlice, AsMutTensor, Tensor};
|
||||
use crate::core_crypto::commons::math::torus::UnsignedTorus;
|
||||
use crate::core_crypto::commons::numeric::{FloatingPoint, Numeric};
|
||||
use concrete_csprng::generators::{BytesPerChild, ChildrenCount, ForkError};
|
||||
#[cfg(feature = "__commons_parallel")]
|
||||
@@ -622,6 +623,27 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update_slice_with_wrapping_add_random_gaussian<Float, Scalar>(
|
||||
&mut self,
|
||||
output: &mut [Scalar],
|
||||
mean: Float,
|
||||
std: Float,
|
||||
) where
|
||||
Scalar: UnsignedTorus,
|
||||
Float: FloatingPoint,
|
||||
(Scalar, Scalar): RandomGenerable<Gaussian<Float>>,
|
||||
{
|
||||
output.chunks_mut(2).for_each(|s| {
|
||||
let (g1, g2) = <(Scalar, Scalar)>::generate_one(self, Gaussian { std, mean });
|
||||
if let Some(elem) = s.get_mut(0) {
|
||||
*elem = (*elem).wrapping_add(g1);
|
||||
}
|
||||
if let Some(elem) = s.get_mut(1) {
|
||||
*elem = (*elem).wrapping_add(g2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Generates a new tensor of floating point values, randomly sampled from a gaussian
|
||||
/// distribution:
|
||||
///
|
||||
|
||||
@@ -179,51 +179,44 @@ pub mod test_tools {
|
||||
|
||||
/// Returns a random plaintext count in [1;max].
|
||||
pub fn random_plaintext_count(max: usize) -> PlaintextCount {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
PlaintextCount((rng.gen::<usize>() % (max - 1)) + 1)
|
||||
let max = std::cmp::max(2, max);
|
||||
PlaintextCount(random_usize_between(1..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random ciphertext count in [1;max].
|
||||
pub fn random_ciphertext_count(max: usize) -> CiphertextCount {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
CiphertextCount((rng.gen::<usize>() % (max - 1)) + 1)
|
||||
let max = std::cmp::max(2, max);
|
||||
CiphertextCount(random_usize_between(1..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random LWE dimension in [1;max].
|
||||
pub fn random_lwe_dimension(max: usize) -> LweDimension {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
LweDimension((rng.gen::<usize>() % (max - 1)) + 1)
|
||||
let max = std::cmp::max(2, max);
|
||||
LweDimension(random_usize_between(1..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random GLWE dimension in [1;max].
|
||||
pub fn random_glwe_dimension(max: usize) -> GlweDimension {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
GlweDimension((rng.gen::<usize>() % (max - 1)) + 1)
|
||||
let max = std::cmp::max(2, max);
|
||||
GlweDimension(random_usize_between(1..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random polynomial size in [2;max].
|
||||
pub fn random_polynomial_size(max: usize) -> PolynomialSize {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
PolynomialSize((rng.gen::<usize>() % (max - 2)) + 2)
|
||||
let max = std::cmp::max(3, max);
|
||||
PolynomialSize(random_usize_between(2..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random base log in [2;max].
|
||||
pub fn random_base_log(max: usize) -> DecompositionBaseLog {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
DecompositionBaseLog((rng.gen::<usize>() % (max - 2)) + 2)
|
||||
let max = std::cmp::max(3, max);
|
||||
DecompositionBaseLog(random_usize_between(2..max + 1))
|
||||
}
|
||||
|
||||
/// Returns a random level count in [2;max].
|
||||
pub fn random_level_count(max: usize) -> DecompositionLevelCount {
|
||||
assert_ne!(max, 0, "Max cannot be 0");
|
||||
let mut rng = rand::thread_rng();
|
||||
DecompositionLevelCount((rng.gen::<usize>() % (max - 2)) + 2)
|
||||
let max = std::cmp::max(3, max);
|
||||
DecompositionLevelCount(random_usize_between(2..max + 1))
|
||||
}
|
||||
|
||||
pub fn random_i32_between(range: std::ops::Range<i32>) -> i32 {
|
||||
|
||||
@@ -113,6 +113,17 @@ pub trait ContiguousEntityContainer: AsRef<[Self::PODElement]> {
|
||||
Self::SelfView::<'_>::create_from(container_right, self_meta),
|
||||
)
|
||||
}
|
||||
|
||||
fn get(&self, index: usize) -> Self::ElementView<'_> {
|
||||
// index here is the number of ref_elements, we need to multiply by the size of a single
|
||||
// element to know where to reference the underlying container
|
||||
|
||||
let start = index * self.get_element_view_pod_size();
|
||||
let stop = start + self.get_element_view_pod_size();
|
||||
let meta = self.get_element_view_creation_metadata();
|
||||
|
||||
Self::ElementView::<'_>::create_from(&self.as_ref()[start..stop], meta)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ContiguousEntityContainerMut:
|
||||
@@ -171,4 +182,15 @@ pub trait ContiguousEntityContainerMut:
|
||||
Self::SelfMutView::<'_>::create_from(container_right, self_meta),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, index: usize) -> Self::ElementMutView<'_> {
|
||||
// index here is the number of ref_elements, we need to multiply by the size of a single
|
||||
// element to know where to reference the underlying container
|
||||
|
||||
let start = index * self.get_element_view_pod_size();
|
||||
let stop = start + self.get_element_view_pod_size();
|
||||
let meta = self.get_element_view_creation_metadata();
|
||||
|
||||
Self::ElementMutView::<'_>::create_from(&mut self.as_mut()[start..stop], meta)
|
||||
}
|
||||
}
|
||||
|
||||
232
tfhe/src/core_crypto/entities/ggsw_ciphertext.rs
Normal file
232
tfhe/src/core_crypto/entities/ggsw_ciphertext.rs
Normal file
@@ -0,0 +1,232 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct GgswCiphertextBase<C: Container> {
|
||||
data: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_size: GlweSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GgswCiphertextBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GgswCiphertextBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ggsw_ciphertext_size(
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
) -> usize {
|
||||
decomp_level_count.0 * ggsw_level_matrix_size(glwe_size, polynomial_size)
|
||||
}
|
||||
|
||||
pub fn ggsw_level_matrix_size(glwe_size: GlweSize, polynomial_size: PolynomialSize) -> usize {
|
||||
glwe_size.0 * glwe_size.0 * polynomial_size.0
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> GgswCiphertextBase<C> {
|
||||
pub fn from_container(
|
||||
container: C,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
) -> Self {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
"Got an empty container to create a GgswCiphertextBase"
|
||||
);
|
||||
assert!(
|
||||
container.container_len() % (glwe_size.0 * glwe_size.0 * polynomial_size.0) == 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by glwe_size * glwe_size * polynomial_size: {}. \
|
||||
Got container length: {} and glwe_size: {glwe_size:?}, \
|
||||
polynomial_size: {polynomial_size:?}.",
|
||||
glwe_size.0 * glwe_size.0 * polynomial_size.0,
|
||||
container.container_len()
|
||||
);
|
||||
|
||||
GgswCiphertextBase {
|
||||
data: container,
|
||||
polynomial_size,
|
||||
glwe_size,
|
||||
decomp_base_log,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
self.glwe_size
|
||||
}
|
||||
|
||||
pub fn decomposition_base_log(&self) -> DecompositionBaseLog {
|
||||
self.decomp_base_log
|
||||
}
|
||||
|
||||
pub fn decomposition_level_count(&self) -> DecompositionLevelCount {
|
||||
DecompositionLevelCount(self.data.container_len() / self.ggsw_level_matrix_size())
|
||||
}
|
||||
|
||||
pub fn ggsw_level_matrix_size(&self) -> usize {
|
||||
// GlweSize GlweCiphertext(glwe_size, polynomial_size) per level
|
||||
ggsw_level_matrix_size(self.glwe_size, self.polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
pub type GgswCiphertext<Scalar> = GgswCiphertextBase<Vec<Scalar>>;
|
||||
pub type GgswCiphertextView<'data, Scalar> = GgswCiphertextBase<&'data [Scalar]>;
|
||||
pub type GgswCiphertextMutView<'data, Scalar> = GgswCiphertextBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> GgswCiphertext<Scalar> {
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
) -> GgswCiphertext<Scalar> {
|
||||
GgswCiphertext::from_container(
|
||||
vec![fill_with; ggsw_ciphertext_size(glwe_size, polynomial_size, decomp_level_count)],
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GgswCiphertextCreationMetadata(
|
||||
pub GlweSize,
|
||||
pub PolynomialSize,
|
||||
pub DecompositionBaseLog,
|
||||
);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for GgswCiphertextBase<C> {
|
||||
type Metadata = GgswCiphertextCreationMetadata;
|
||||
|
||||
#[inline]
|
||||
fn create_from(from: C, meta: Self::Metadata) -> GgswCiphertextBase<C> {
|
||||
let GgswCiphertextCreationMetadata(glwe_size, polynomial_size, decomp_base_log) = meta;
|
||||
GgswCiphertextBase::from_container(from, glwe_size, polynomial_size, decomp_base_log)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GgswLevelMatrix<C: Container> {
|
||||
data: C,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
}
|
||||
|
||||
impl<C: Container> GgswLevelMatrix<C> {
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
self.glwe_size
|
||||
}
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn from_container(
|
||||
container: C,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
) -> GgswLevelMatrix<C> {
|
||||
assert!(
|
||||
container.container_len() == ggsw_level_matrix_size(glwe_size, polynomial_size),
|
||||
"The provided container length is not valid. \
|
||||
Expected length of {} (glwe_size * glwe_size * polynomial_size), got {}",
|
||||
ggsw_level_matrix_size(glwe_size, polynomial_size),
|
||||
container.container_len(),
|
||||
);
|
||||
|
||||
GgswLevelMatrix {
|
||||
data: container,
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_glwe_list(&self) -> GlweCiphertextListView<'_, C::Element> {
|
||||
GlweCiphertextListView::from_container(
|
||||
self.data.as_ref(),
|
||||
self.polynomial_size,
|
||||
self.glwe_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> GgswLevelMatrix<C> {
|
||||
pub fn as_mut_glwe_list(&mut self) -> GlweCiphertextListMutView<'_, C::Element> {
|
||||
GlweCiphertextListMutView::from_container(
|
||||
self.data.as_mut(),
|
||||
self.polynomial_size,
|
||||
self.glwe_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GgswLevelMatrixCreationMetadata(pub GlweSize, pub PolynomialSize);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for GgswLevelMatrix<C> {
|
||||
type Metadata = GgswLevelMatrixCreationMetadata;
|
||||
|
||||
#[inline]
|
||||
fn create_from(from: C, meta: Self::Metadata) -> GgswLevelMatrix<C> {
|
||||
let GgswLevelMatrixCreationMetadata(glwe_size, polynomial_size) = meta;
|
||||
GgswLevelMatrix::from_container(from, glwe_size, polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Container> ContiguousEntityContainer for GgswCiphertextBase<C> {
|
||||
type PODElement = C::Element;
|
||||
|
||||
type ElementViewMetadata = GgswLevelMatrixCreationMetadata;
|
||||
|
||||
type ElementView<'this> = GgswLevelMatrix<&'this [Self::PODElement]>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfViewMetadata = ();
|
||||
|
||||
type SelfView<'this> = DummyCreateFrom
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
|
||||
GgswLevelMatrixCreationMetadata(self.glwe_size, self.polynomial_size)
|
||||
}
|
||||
|
||||
fn get_element_view_pod_size(&self) -> usize {
|
||||
self.ggsw_level_matrix_size()
|
||||
}
|
||||
|
||||
/// Unimplement for [`GgswCiphertextBase`]. At the moment it does not make sense to
|
||||
/// return "sub" GgswCiphertext.
|
||||
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
|
||||
unimplemented!(
|
||||
"This function is not supported for GgswCiphertext. \
|
||||
At the moment it does not make sense to return 'sub' GgswCiphertext."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> ContiguousEntityContainerMut for GgswCiphertextBase<C> {
|
||||
type ElementMutView<'this> = GgswLevelMatrix<&'this mut [Self::PODElement]>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfMutView<'this> = DummyCreateFrom
|
||||
where
|
||||
Self: 'this;
|
||||
}
|
||||
183
tfhe/src/core_crypto/entities/ggsw_ciphertext_list.rs
Normal file
183
tfhe/src/core_crypto/entities/ggsw_ciphertext_list.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct GgswCiphertextListBase<C: Container> {
|
||||
data: C,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GgswCiphertextListBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GgswCiphertextListBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> GgswCiphertextListBase<C> {
|
||||
pub fn from_container(
|
||||
container: C,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
) -> GgswCiphertextListBase<C> {
|
||||
assert!(
|
||||
container.container_len()
|
||||
% (decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0)
|
||||
== 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by decomp_level_count * glwe_size * glwe_size * polynomial_size: \
|
||||
{}.Got container length: {} and decomp_level_count: {decomp_level_count:?}, \
|
||||
glwe_size: {glwe_size:?}, polynomial_size: {polynomial_size:?}",
|
||||
decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0,
|
||||
container.container_len()
|
||||
);
|
||||
|
||||
GgswCiphertextListBase {
|
||||
data: container,
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
self.glwe_size
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn decomposition_base_log(&self) -> DecompositionBaseLog {
|
||||
self.decomp_base_log
|
||||
}
|
||||
|
||||
pub fn decomposition_level_count(&self) -> DecompositionLevelCount {
|
||||
self.decomp_level_count
|
||||
}
|
||||
|
||||
pub fn ggsw_ciphertext_count(&self) -> GgswCiphertextCount {
|
||||
GgswCiphertextCount(
|
||||
self.data.container_len()
|
||||
/ ggsw_ciphertext_size(
|
||||
self.glwe_size,
|
||||
self.polynomial_size,
|
||||
self.decomp_level_count,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type GgswCiphertextList<Scalar> = GgswCiphertextListBase<Vec<Scalar>>;
|
||||
pub type GgswCiphertextListView<'data, Scalar> = GgswCiphertextListBase<&'data [Scalar]>;
|
||||
pub type GgswCiphertextListMutView<'data, Scalar> = GgswCiphertextListBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> GgswCiphertextList<Scalar> {
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
glwe_size: GlweSize,
|
||||
polynomial_size: PolynomialSize,
|
||||
decomp_base_log: DecompositionBaseLog,
|
||||
decomp_level_count: DecompositionLevelCount,
|
||||
ciphertext_count: GgswCiphertextCount,
|
||||
) -> GgswCiphertextList<Scalar> {
|
||||
GgswCiphertextListBase::from_container(
|
||||
vec![
|
||||
fill_with;
|
||||
ciphertext_count.0
|
||||
* ggsw_ciphertext_size(glwe_size, polynomial_size, decomp_level_count)
|
||||
],
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GgswCiphertextListCreationMetadata(
|
||||
pub GlweSize,
|
||||
pub PolynomialSize,
|
||||
pub DecompositionBaseLog,
|
||||
pub DecompositionLevelCount,
|
||||
);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for GgswCiphertextListBase<C> {
|
||||
type Metadata = GgswCiphertextListCreationMetadata;
|
||||
|
||||
#[inline]
|
||||
fn create_from(from: C, meta: Self::Metadata) -> GgswCiphertextListBase<C> {
|
||||
let GgswCiphertextListCreationMetadata(
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
) = meta;
|
||||
GgswCiphertextListBase::from_container(
|
||||
from,
|
||||
glwe_size,
|
||||
polynomial_size,
|
||||
decomp_base_log,
|
||||
decomp_level_count,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Container> ContiguousEntityContainer for GgswCiphertextListBase<C> {
|
||||
type PODElement = C::Element;
|
||||
|
||||
type ElementViewMetadata = GgswCiphertextCreationMetadata;
|
||||
|
||||
type ElementView<'this> = GgswCiphertextView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfViewMetadata = GgswCiphertextListCreationMetadata;
|
||||
|
||||
type SelfView<'this> = GgswCiphertextListView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
fn get_element_view_creation_metadata(&self) -> GgswCiphertextCreationMetadata {
|
||||
GgswCiphertextCreationMetadata(self.glwe_size, self.polynomial_size, self.decomp_base_log)
|
||||
}
|
||||
|
||||
fn get_element_view_pod_size(&self) -> usize {
|
||||
ggsw_ciphertext_size(
|
||||
self.glwe_size,
|
||||
self.polynomial_size,
|
||||
self.decomp_level_count,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
|
||||
GgswCiphertextListCreationMetadata(
|
||||
self.glwe_size,
|
||||
self.polynomial_size,
|
||||
self.decomp_base_log,
|
||||
self.decomp_level_count,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> ContiguousEntityContainerMut for GgswCiphertextListBase<C> {
|
||||
type ElementMutView<'this> = GgswCiphertextMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfMutView<'this> = GgswCiphertextListMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
}
|
||||
250
tfhe/src/core_crypto/entities/glwe_ciphertext.rs
Normal file
250
tfhe/src/core_crypto/entities/glwe_ciphertext.rs
Normal file
@@ -0,0 +1,250 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct GlweBody<C: Container> {
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<C: Container> GlweBody<C> {
|
||||
pub fn from_container(container: C) -> GlweBody<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
"Got an empty container to create a GlweBody"
|
||||
);
|
||||
GlweBody { data: container }
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
PolynomialSize(self.data.container_len())
|
||||
}
|
||||
|
||||
pub fn as_polynomial(&self) -> PolynomialView<'_, C::Element> {
|
||||
PolynomialView::from_container(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> GlweBody<C> {
|
||||
pub fn as_mut_polynomial(&mut self) -> PolynomialMutView<'_, C::Element> {
|
||||
PolynomialMutView::from_container(self.as_mut())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GlweMask<C: Container> {
|
||||
data: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
}
|
||||
|
||||
impl<C: Container> GlweMask<C> {
|
||||
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> Self {
|
||||
assert!(
|
||||
container.container_len() % polynomial_size.0 == 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by polynomial_size. \
|
||||
Got container length: {} and polynomial_size: {polynomial_size:?}.",
|
||||
container.container_len()
|
||||
);
|
||||
GlweMask {
|
||||
data: container,
|
||||
polynomial_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn glwe_dimension(&self) -> GlweDimension {
|
||||
GlweDimension(self.data.container_len() / self.polynomial_size.0)
|
||||
}
|
||||
|
||||
pub fn as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
|
||||
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> GlweMask<C> {
|
||||
pub fn as_mut_polynomial_list(&mut self) -> PolynomialListMutView<'_, C::Element> {
|
||||
let polynomial_size = self.polynomial_size;
|
||||
PolynomialListMutView::from_container(self.as_mut(), polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweMask<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweMask<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweBody<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweBody<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn glwe_ciphertext_size(polynomial_size: PolynomialSize, glwe_size: GlweSize) -> usize {
|
||||
polynomial_size.0 * glwe_size.0
|
||||
}
|
||||
|
||||
pub fn glwe_ciphertext_mask_size(
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_dimension: GlweDimension,
|
||||
) -> usize {
|
||||
polynomial_size.0 * glwe_dimension.0
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GlweCiphertextBase<C: Container> {
|
||||
data: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweCiphertextBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertextBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertextBase<C> {
|
||||
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> GlweCiphertextBase<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
"Got an empty container to create a GlweCiphertext"
|
||||
);
|
||||
assert!(
|
||||
container.container_len() % polynomial_size.0 == 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by polynomial_size. \
|
||||
Got container length: {} and polynomial_size: {polynomial_size:?}.",
|
||||
container.container_len()
|
||||
);
|
||||
GlweCiphertextBase {
|
||||
data: container,
|
||||
polynomial_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
GlweSize(self.as_ref().container_len() / self.polynomial_size.0)
|
||||
}
|
||||
|
||||
pub fn get_mask_and_body(&self) -> (GlweMask<&[Scalar]>, GlweBody<&[Scalar]>) {
|
||||
let (mask, body) = self.data.as_ref().split_at(glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
));
|
||||
|
||||
(
|
||||
GlweMask::from_container(mask, self.polynomial_size),
|
||||
GlweBody::from_container(body),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_body(&self) -> GlweBody<&[Scalar]> {
|
||||
let body = &self.data.as_ref()[glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
)..];
|
||||
|
||||
GlweBody::from_container(body)
|
||||
}
|
||||
|
||||
pub fn get_mask(&self) -> GlweMask<&[Scalar]> {
|
||||
GlweMask::from_container(
|
||||
&self.as_ref()[0..glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
)],
|
||||
self.polynomial_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertextBase<C> {
|
||||
pub fn get_mut_mask_and_body(&mut self) -> (GlweMask<&mut [Scalar]>, GlweBody<&mut [Scalar]>) {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
|
||||
let (mask, body) = self
|
||||
.data
|
||||
.as_mut()
|
||||
.split_at_mut(glwe_ciphertext_mask_size(polynomial_size, glwe_dimension));
|
||||
|
||||
(
|
||||
GlweMask::from_container(mask, polynomial_size),
|
||||
GlweBody::from_container(body),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_mut_body(&mut self) -> GlweBody<&mut [Scalar]> {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
|
||||
let body =
|
||||
&mut self.data.as_mut()[glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)..];
|
||||
|
||||
GlweBody::from_container(body)
|
||||
}
|
||||
|
||||
pub fn get_mut_mask(&mut self) -> GlweMask<&mut [Scalar]> {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
|
||||
GlweMask::from_container(
|
||||
&mut self.as_mut()[0..glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)],
|
||||
polynomial_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type GlweCiphertext<Scalar> = GlweCiphertextBase<Vec<Scalar>>;
|
||||
pub type GlweCiphertextView<'data, Scalar> = GlweCiphertextBase<&'data [Scalar]>;
|
||||
pub type GlweCiphertextMutView<'data, Scalar> = GlweCiphertextBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> GlweCiphertext<Scalar> {
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_size: GlweSize,
|
||||
) -> GlweCiphertext<Scalar> {
|
||||
GlweCiphertext::from_container(
|
||||
vec![fill_with; glwe_ciphertext_size(polynomial_size, glwe_size)],
|
||||
polynomial_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GlweCiphertextCreationMetadata(pub PolynomialSize);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for GlweCiphertextBase<C> {
|
||||
type Metadata = GlweCiphertextCreationMetadata;
|
||||
|
||||
#[inline]
|
||||
fn create_from(from: C, meta: Self::Metadata) -> GlweCiphertextBase<C> {
|
||||
let GlweCiphertextCreationMetadata(polynomial_size) = meta;
|
||||
GlweCiphertextBase::from_container(from, polynomial_size)
|
||||
}
|
||||
}
|
||||
126
tfhe/src/core_crypto/entities/glwe_ciphertext_list.rs
Normal file
126
tfhe/src/core_crypto/entities/glwe_ciphertext_list.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct GlweCiphertextListBase<C: Container> {
|
||||
data: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_size: GlweSize,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for GlweCiphertextListBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertextListBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertextListBase<C> {
|
||||
pub fn from_container(
|
||||
container: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_size: GlweSize,
|
||||
) -> GlweCiphertextListBase<C> {
|
||||
assert!(
|
||||
container.container_len() % glwe_ciphertext_size(polynomial_size, glwe_size) == 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by polynomial_size * glwe_size. \
|
||||
Got container length: {}, polynomial_size: {polynomial_size:?} glwe_size: {glwe_size:?}.",
|
||||
container.container_len()
|
||||
);
|
||||
GlweCiphertextListBase {
|
||||
data: container,
|
||||
polynomial_size,
|
||||
glwe_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
self.glwe_size
|
||||
}
|
||||
|
||||
pub fn glwe_ciphertext_count(&self) -> GlweCiphertextCount {
|
||||
GlweCiphertextCount(
|
||||
self.data.container_len() / glwe_ciphertext_size(self.polynomial_size, self.glwe_size),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type GlweCiphertextList<Scalar> = GlweCiphertextListBase<Vec<Scalar>>;
|
||||
pub type GlweCiphertextListView<'data, Scalar> = GlweCiphertextListBase<&'data [Scalar]>;
|
||||
pub type GlweCiphertextListMutView<'data, Scalar> = GlweCiphertextListBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> GlweCiphertextList<Scalar> {
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_size: GlweSize,
|
||||
ciphertext_count: GlweCiphertextCount,
|
||||
) -> GlweCiphertextList<Scalar> {
|
||||
GlweCiphertextList::from_container(
|
||||
vec![fill_with; glwe_ciphertext_size(polynomial_size, glwe_size) * ciphertext_count.0],
|
||||
polynomial_size,
|
||||
glwe_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GlweCiphertextListCreationMetadata(pub PolynomialSize, pub GlweSize);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for GlweCiphertextListBase<C> {
|
||||
type Metadata = GlweCiphertextListCreationMetadata;
|
||||
|
||||
#[inline]
|
||||
fn create_from(from: C, meta: Self::Metadata) -> GlweCiphertextListBase<C> {
|
||||
let GlweCiphertextListCreationMetadata(polynomial_size, glwe_size) = meta;
|
||||
GlweCiphertextListBase::from_container(from, polynomial_size, glwe_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Container> ContiguousEntityContainer for GlweCiphertextListBase<C> {
|
||||
type PODElement = C::Element;
|
||||
|
||||
type ElementViewMetadata = GlweCiphertextCreationMetadata;
|
||||
|
||||
type ElementView<'this> = GlweCiphertextView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfViewMetadata = GlweCiphertextListCreationMetadata;
|
||||
|
||||
type SelfView<'this> = GlweCiphertextListView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
fn get_element_view_creation_metadata(&self) -> GlweCiphertextCreationMetadata {
|
||||
GlweCiphertextCreationMetadata(self.polynomial_size())
|
||||
}
|
||||
|
||||
fn get_element_view_pod_size(&self) -> usize {
|
||||
glwe_ciphertext_size(self.polynomial_size(), self.glwe_size())
|
||||
}
|
||||
|
||||
fn get_self_view_creation_metadata(&self) -> GlweCiphertextListCreationMetadata {
|
||||
GlweCiphertextListCreationMetadata(self.polynomial_size(), self.glwe_size())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> ContiguousEntityContainerMut for GlweCiphertextListBase<C> {
|
||||
type ElementMutView<'this> = GlweCiphertextMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfMutView<'this> = GlweCiphertextListMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::{GlweDimension, PolynomialSize};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GlweSecretKeyBase<C: Container> {
|
||||
@@ -50,6 +50,10 @@ impl<Scalar, C: Container<Element = Scalar>> GlweSecretKeyBase<C> {
|
||||
pub fn into_lwe_secret_key(self) -> LweSecretKeyBase<C> {
|
||||
LweSecretKeyBase::from_container(self.data)
|
||||
}
|
||||
|
||||
pub fn as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
|
||||
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
pub type GlweSecretKey<Scalar> = GlweSecretKeyBase<Vec<Scalar>>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::specification::parameters::{LweDimension, LweSize};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct LweBody<T>(pub T);
|
||||
pub struct LweMask<C: Container> {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::{LweCiphertextCount, LweSize};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct LweCiphertextListBase<C: Container> {
|
||||
data: C,
|
||||
lwe_size: LweSize,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::{
|
||||
DecompositionBaseLog, DecompositionLevelCount, LweDimension, LweSize,
|
||||
};
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct LweKeyswitchKeyBase<C: Container> {
|
||||
@@ -132,7 +130,7 @@ impl<C: Container> ContiguousEntityContainer for LweKeyswitchKeyBase<C> {
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
|
||||
fn get_element_view_creation_metadata(&self) -> LweCiphertextListCreationMetadata {
|
||||
LweCiphertextListCreationMetadata(self.output_lwe_size())
|
||||
}
|
||||
|
||||
@@ -142,8 +140,11 @@ impl<C: Container> ContiguousEntityContainer for LweKeyswitchKeyBase<C> {
|
||||
|
||||
/// Unimplement for [`LweKeyswitchKeyBase`]. At the moment it does not make sense to
|
||||
/// return "sub" keyswitch keys.
|
||||
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
|
||||
unimplemented!("At the moment it does not make sense to return 'sub' keyswitch keys.")
|
||||
fn get_self_view_creation_metadata(&self) {
|
||||
unimplemented!(
|
||||
"This function is not supported for LweKeyswitchKey. \
|
||||
At the moment it does not make sense to return 'sub' keyswitch keys."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
pub mod cleartext;
|
||||
pub mod ggsw_ciphertext;
|
||||
pub mod ggsw_ciphertext_list;
|
||||
pub mod glwe_ciphertext;
|
||||
pub mod glwe_ciphertext_list;
|
||||
pub mod glwe_secret_key;
|
||||
pub mod lwe_ciphertext;
|
||||
pub mod lwe_ciphertext_list;
|
||||
@@ -6,8 +10,14 @@ pub mod lwe_keyswitch_key;
|
||||
pub mod lwe_secret_key;
|
||||
pub mod plaintext;
|
||||
pub mod plaintext_list;
|
||||
pub mod polynomial;
|
||||
pub mod polynomial_list;
|
||||
|
||||
pub use cleartext::*;
|
||||
pub use ggsw_ciphertext::*;
|
||||
pub use ggsw_ciphertext_list::*;
|
||||
pub use glwe_ciphertext::*;
|
||||
pub use glwe_ciphertext_list::*;
|
||||
pub use glwe_secret_key::*;
|
||||
pub use lwe_ciphertext::*;
|
||||
pub use lwe_ciphertext_list::*;
|
||||
@@ -15,3 +25,5 @@ pub use lwe_keyswitch_key::*;
|
||||
pub use lwe_secret_key::*;
|
||||
pub use plaintext::*;
|
||||
pub use plaintext_list::*;
|
||||
pub use polynomial::*;
|
||||
pub use polynomial_list::*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::PlaintextCount;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct PlaintextListBase<C: Container> {
|
||||
data: C,
|
||||
|
||||
75
tfhe/src/core_crypto/entities/polynomial.rs
Normal file
75
tfhe/src/core_crypto/entities/polynomial.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
pub struct PolynomialBase<C: Container> {
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for PolynomialBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for PolynomialBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> PolynomialBase<C> {
|
||||
pub fn from_container(container: C) -> PolynomialBase<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
"Got an empty container to create a Polynomial"
|
||||
);
|
||||
PolynomialBase { data: container }
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
PolynomialSize(self.data.container_len())
|
||||
}
|
||||
|
||||
pub fn degree(&self) -> usize {
|
||||
self.polynomial_size().0 - 1
|
||||
}
|
||||
}
|
||||
|
||||
pub type Polynomial<Scalar> = PolynomialBase<Vec<Scalar>>;
|
||||
pub type PolynomialView<'data, Scalar> = PolynomialBase<&'data [Scalar]>;
|
||||
pub type PolynomialMutView<'data, Scalar> = PolynomialBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar> Polynomial<Vec<Scalar>>
|
||||
where
|
||||
Scalar: Copy,
|
||||
{
|
||||
pub fn new(fill_with: Scalar, polynomial_size: PolynomialSize) -> Polynomial<Scalar> {
|
||||
Polynomial::from_container(vec![fill_with; polynomial_size.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Container> Deref for PolynomialBase<C> {
|
||||
type Target = [C::Element];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> DerefMut for PolynomialBase<C> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PolynomialCreationMetadata();
|
||||
|
||||
impl<C: Container> CreateFrom<C> for PolynomialBase<C> {
|
||||
type Metadata = PolynomialCreationMetadata;
|
||||
|
||||
fn create_from(from: C, _: Self::Metadata) -> PolynomialBase<C> {
|
||||
PolynomialBase::from_container(from)
|
||||
}
|
||||
}
|
||||
111
tfhe/src/core_crypto/entities/polynomial_list.rs
Normal file
111
tfhe/src/core_crypto/entities/polynomial_list.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
use crate::core_crypto::specification::parameters::*;
|
||||
|
||||
pub struct PolynomialListBase<C: Container> {
|
||||
data: C,
|
||||
polynomial_size: PolynomialSize,
|
||||
}
|
||||
|
||||
impl<T, C: Container<Element = T>> AsRef<[T]> for PolynomialListBase<C> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for PolynomialListBase<C> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self.data.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> PolynomialListBase<C> {
|
||||
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> PolynomialListBase<C> {
|
||||
assert!(
|
||||
container.container_len() % polynomial_size.0 == 0,
|
||||
"The provided container length is not valid. \
|
||||
It needs to be dividable by polynomial_size. \
|
||||
Got container length: {} and polynomial_size: {polynomial_size:?}.",
|
||||
container.container_len()
|
||||
);
|
||||
PolynomialListBase {
|
||||
data: container,
|
||||
polynomial_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
pub fn polynomial_count(&self) -> PolynomialCount {
|
||||
PolynomialCount(self.data.container_len())
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolynomialList<Scalar> = PolynomialListBase<Vec<Scalar>>;
|
||||
pub type PolynomialListView<'data, Scalar> = PolynomialListBase<&'data [Scalar]>;
|
||||
pub type PolynomialListMutView<'data, Scalar> = PolynomialListBase<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> PolynomialList<Scalar> {
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
polynomial_size: PolynomialSize,
|
||||
polynomial_count: PolynomialCount,
|
||||
) -> PolynomialList<Scalar> {
|
||||
PolynomialList::from_container(
|
||||
vec![fill_with; polynomial_size.0 * polynomial_count.0],
|
||||
polynomial_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PolynomialListCreationMetadata(pub PolynomialSize);
|
||||
|
||||
impl<C: Container> CreateFrom<C> for PolynomialListBase<C> {
|
||||
type Metadata = PolynomialListCreationMetadata;
|
||||
|
||||
fn create_from(from: C, meta: Self::Metadata) -> PolynomialListBase<C> {
|
||||
let PolynomialListCreationMetadata(polynomial_size) = meta;
|
||||
PolynomialListBase::from_container(from, polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Container> ContiguousEntityContainer for PolynomialListBase<C> {
|
||||
type PODElement = C::Element;
|
||||
|
||||
type ElementViewMetadata = PolynomialCreationMetadata;
|
||||
|
||||
type ElementView<'this> = PolynomialView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfViewMetadata = PolynomialListCreationMetadata;
|
||||
|
||||
type SelfView<'this> = PolynomialListView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
fn get_element_view_creation_metadata(&self) -> Self::ElementViewMetadata {
|
||||
PolynomialCreationMetadata()
|
||||
}
|
||||
|
||||
fn get_element_view_pod_size(&self) -> usize {
|
||||
self.polynomial_size().0
|
||||
}
|
||||
|
||||
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
|
||||
PolynomialListCreationMetadata(self.polynomial_size())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> ContiguousEntityContainerMut for PolynomialListBase<C> {
|
||||
type ElementMutView<'this> = PolynomialMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
|
||||
type SelfMutView<'this> = PolynomialListMutView<'this, Self::PODElement>
|
||||
where
|
||||
Self: 'this;
|
||||
}
|
||||
Reference in New Issue
Block a user