Skip to content

Commit

Permalink
chore(core): change rng tests to better avoid false failures
Browse files Browse the repository at this point in the history
- we still check we generate non zero values but add retry conditions or
have less stringent checks, to allow some values to be zero for example as
it's a valid value that can be generated
- each test suite (test and doctest) for these tests ran 1000 times without
failure
  • Loading branch information
IceTDrinker committed Apr 24, 2023
1 parent 0233a69 commit af936df
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 29 deletions.
96 changes: 77 additions & 19 deletions tfhe/src/core_crypto/commons/generators/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,18 @@ mod test {
let bits = (Scalar::BITS / 2) as i32;

for _ in 0..1000 {
let val: Scalar = gen.random_noise(StandardDev(2.0f64.powi(-bits)));
let mut retries = 100;

let mut val = Scalar::ZERO;
while retries >= 0 {
val = gen.random_noise(StandardDev(2.0f64.powi(-bits)));
if val != Scalar::ZERO {
break;
}
retries -= 1;
}

assert!(retries != 0);
assert!(val != Scalar::ZERO);
}
}
Expand All @@ -636,8 +647,19 @@ mod test {
let bits = (Scalar::BITS / 2) as i32;

for _ in 0..1000 {
let val: Scalar =
gen.random_noise_custom_mod(StandardDev(2.0f64.powi(-bits)), ciphertext_modulus);
let mut retries = 100;

let mut val = Scalar::ZERO;
while retries >= 0 {
val = gen
.random_noise_custom_mod(StandardDev(2.0f64.powi(-bits)), ciphertext_modulus);
if val != Scalar::ZERO {
break;
}
retries -= 1;
}

assert!(retries != 0);
assert!(val != Scalar::ZERO);
}
}
Expand Down Expand Up @@ -677,9 +699,18 @@ mod test {

let bits = (Scalar::BITS / 2) as i32;

let mut slice = vec![Scalar::ZERO; 1000];
gen.fill_slice_with_random_noise(&mut slice, StandardDev(2.0f64.powi(-bits)));
assert!(slice.iter().all(|&x| x != Scalar::ZERO))
let mut vec = vec![Scalar::ZERO; 1000];
let mut retries = 100;
while retries >= 0 {
gen.fill_slice_with_random_noise(&mut vec, StandardDev(2.0f64.powi(-bits)));
if vec.iter().all(|&x| x != Scalar::ZERO) {
break;
}

retries -= 1;
}
assert!(retries != 0);
assert!(vec.iter().all(|&x| x != Scalar::ZERO));
}

#[test]
Expand All @@ -704,13 +735,22 @@ mod test {

let bits = (Scalar::BITS / 2) as i32;

let mut slice = vec![Scalar::ZERO; 1000];
gen.fill_slice_with_random_noise_custom_mod(
&mut slice,
StandardDev(2.0f64.powi(-bits)),
ciphertext_modulus,
);
assert!(slice.iter().all(|&x| x != Scalar::ZERO))
let mut vec = vec![Scalar::ZERO; 1000];
let mut retries = 100;
while retries >= 0 {
gen.fill_slice_with_random_noise_custom_mod(
&mut vec,
StandardDev(2.0f64.powi(-bits)),
ciphertext_modulus,
);
if vec.iter().all(|&x| x != Scalar::ZERO) {
break;
}

retries -= 1;
}
assert!(retries != 0);
assert!(vec.iter().all(|&x| x != Scalar::ZERO));
}

#[test]
Expand Down Expand Up @@ -746,9 +786,18 @@ mod test {
fn mask_gen_slice_native<Scalar: UnsignedTorus>() {
let mut gen = new_encryption_random_generator();

let mut slice = vec![Scalar::ZERO; 1000];
gen.fill_slice_with_random_mask(&mut slice);
assert!(slice.iter().all(|&x| x != Scalar::ZERO))
let mut vec = vec![Scalar::ZERO; 1000];
let mut retries = 100;
while retries >= 0 {
gen.fill_slice_with_random_mask(&mut vec);
if vec.iter().all(|&x| x != Scalar::ZERO) {
break;
}

retries -= 1;
}
assert!(retries != 0);
assert!(vec.iter().all(|&x| x != Scalar::ZERO));
}

#[test]
Expand All @@ -771,9 +820,18 @@ mod test {
) {
let mut gen = new_encryption_random_generator();

let mut slice = vec![Scalar::ZERO; 1000];
gen.fill_slice_with_random_mask_custom_mod(&mut slice, ciphertext_modulus);
assert!(slice.iter().all(|&x| x != Scalar::ZERO))
let mut vec = vec![Scalar::ZERO; 1000];
let mut retries = 100;
while retries >= 0 {
gen.fill_slice_with_random_mask_custom_mod(&mut vec, ciphertext_modulus);
if vec.iter().all(|&x| x != Scalar::ZERO) {
break;
}

retries -= 1;
}
assert!(retries != 0);
assert!(vec.iter().all(|&x| x != Scalar::ZERO));
}

#[test]
Expand Down
16 changes: 6 additions & 10 deletions tfhe/src/core_crypto/commons/math/random/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// let mut generator = RandomGenerator::<SoftwareRandomGenerator>::new(Seed(0));
/// let mut vec = vec![0u32; 1000];
/// generator.fill_slice_with_random_uniform(&mut vec);
/// assert!(vec.iter().all(|&x| x != 0));
/// assert!(vec.iter().any(|&x| x != 0));
/// ```
pub fn fill_slice_with_random_uniform<Scalar>(&mut self, output: &mut [Scalar])
where
Expand All @@ -202,7 +202,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// &mut vec,
/// CiphertextModulus::try_new_power_of_2(31).unwrap(),
/// );
/// assert!(vec.iter().all(|&x| x != 0));
/// assert!(vec.iter().any(|&x| x != 0));
/// ```
pub fn fill_slice_with_random_uniform_custom_mod<Scalar>(
&mut self,
Expand Down Expand Up @@ -351,15 +351,11 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// // check that both samples are in 6 sigmas.
/// assert!(g1.abs() <= 6.);
/// assert!(g2.abs() <= 6.);
/// assert!(g1 != 0.);
/// assert!(g2 != 0.);
/// // for f64
/// let (g1, g2): (f64, f64) = generator.random_gaussian(0. as f64, 1. as f64);
/// // check that both samples are in 6 sigmas.
/// assert!(g1.abs() <= 6.);
/// assert!(g2.abs() <= 6.);
/// assert!(g1 != 0.);
/// assert!(g2 != 0.);
/// ```
pub fn random_gaussian<Float, Scalar>(&mut self, mean: Float, std: Float) -> (Scalar, Scalar)
where
Expand All @@ -380,7 +376,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// let mut generator = RandomGenerator::<SoftwareRandomGenerator>::new(Seed(0));
/// let mut vec = vec![0f32; 1000];
/// generator.fill_slice_with_random_gaussian(&mut vec, 0., 1.);
/// assert!(vec.iter().all(|&x| x != 0.));
/// assert!(vec.iter().any(|&x| x != 0.));
/// ```
pub fn fill_slice_with_random_gaussian<Float, Scalar>(
&mut self,
Expand Down Expand Up @@ -419,7 +415,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// 1.,
/// CiphertextModulus::try_new_power_of_2(63).unwrap(),
/// );
/// assert!(vec.iter().all(|&x| x != 0));
/// assert!(vec.iter().any(|&x| x != 0));
/// ```
pub fn fill_slice_with_random_gaussian_custom_mod<Float, Scalar>(
&mut self,
Expand Down Expand Up @@ -464,7 +460,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// let mut generator = RandomGenerator::<SoftwareRandomGenerator>::new(Seed(0));
/// let mut vec = vec![0u32; 1000];
/// generator.unsigned_torus_slice_wrapping_add_random_gaussian_assign(&mut vec, 0., 1.);
/// assert!(vec.iter().all(|&x| x != 0));
/// assert!(vec.iter().any(|&x| x != 0));
/// ```
pub fn unsigned_torus_slice_wrapping_add_random_gaussian_assign<Float, Scalar>(
&mut self,
Expand Down Expand Up @@ -503,7 +499,7 @@ impl<G: ByteRandomGenerator> RandomGenerator<G> {
/// 1.,
/// CiphertextModulus::try_new_power_of_2(31).unwrap(),
/// );
/// assert!(vec.iter().all(|&x| x != 0));
/// assert!(vec.iter().any(|&x| x != 0));
/// ```
pub fn unsigned_torus_slice_wrapping_add_random_gaussian_custom_mod_assign<Float, Scalar>(
&mut self,
Expand Down

0 comments on commit af936df

Please sign in to comment.