From 40c06d714fd67c05d3d5c828b2e731fb15090187 Mon Sep 17 00:00:00 2001
From: "Mayeul@Zama" <69792125+mayeul-zama@users.noreply.github.com>
Date: Tue, 19 Mar 2024 15:53:59 +0100
Subject: [PATCH 01/12] fix(shortint): fix and rename tests
---
.../src/shortint/server_key/tests/shortint.rs | 30 +++++++++----------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/tfhe/src/shortint/server_key/tests/shortint.rs b/tfhe/src/shortint/server_key/tests/shortint.rs
index 03a4c7c581..0bca1ebe3b 100644
--- a/tfhe/src/shortint/server_key/tests/shortint.rs
+++ b/tfhe/src/shortint/server_key/tests/shortint.rs
@@ -216,6 +216,12 @@ create_parametrized_test!(shortint_default_scalar_bitor);
create_parametrized_test!(shortint_default_scalar_bitxor);
create_parametrized_test!(shortint_trivial_pbs);
create_parametrized_test!(shortint_trivial_pbs_many_lut);
+create_parametrized_test!(
+ shortint_encrypt_with_message_modulus_unchecked_mul_lsb_small_carry_and_add
+);
+create_parametrized_test!(
+ shortint_encrypt_with_message_and_carry_modulus_unchecked_mul_lsb_small_carry_and_add
+);
// Public key tests are limited to small parameter sets to avoid blowing up memory and large testing
// times. Compressed keygen takes 20 minutes for params 2_2 and for encryption as well.
@@ -279,12 +285,6 @@ create_parametrized_test_bivariate_pbs_compliant!(shortint_default_mul_msb);
create_parametrized_test_bivariate_pbs_compliant!(
shortint_keyswitch_bivariate_programmable_bootstrap
);
-create_parametrized_test_bivariate_pbs_compliant!(
- shortint_encrypt_with_message_modulus_smart_add_and_mul
-);
-create_parametrized_test_bivariate_pbs_compliant!(
- shortint_encrypt_with_message_and_carry_modulus_smart_add_and_mul
-);
create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less_or_equal_trivial);
/// test encryption and decryption with the LWE client key
@@ -3190,7 +3190,7 @@ where
}
/// test encryption and decryption with the LWE client key
-fn shortint_encrypt_with_message_modulus_smart_add_and_mul
(param: P)
+fn shortint_encrypt_with_message_modulus_unchecked_mul_lsb_small_carry_and_add
(param: P)
where
P: Into,
{
@@ -3198,13 +3198,10 @@ where
let (cks, sks) = (keys.client_key(), keys.server_key());
let mut rng = rand::thread_rng();
- let full_mod = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) / 3;
+ let full_mod = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
for _ in 0..NB_TESTS {
- let mut modulus = rng.gen::() % full_mod as u64;
- while modulus == 0 {
- modulus = rng.gen::() % full_mod as u64;
- }
+ let modulus = rng.gen_range(1..full_mod / 2);
let clear1 = rng.gen::() % modulus;
let clear2 = rng.gen::() % modulus;
@@ -3226,8 +3223,9 @@ where
}
/// test encryption and decryption with the LWE client key
-fn shortint_encrypt_with_message_and_carry_modulus_smart_add_and_mul(param: P)
-where
+fn shortint_encrypt_with_message_and_carry_modulus_unchecked_mul_lsb_small_carry_and_add
(
+ param: P,
+) where
P: Into,
{
let keys = KEY_CACHE.get_from_param(param);
@@ -3239,8 +3237,8 @@ where
let param_carry_mod = cks.parameters.carry_modulus().0;
for _ in 0..NB_TESTS {
- let msg_modulus = rng.gen_range(2u64..param_msg_mod as u64);
- let carry_modulus = rng.gen_range(2u64..param_carry_mod as u64);
+ let msg_modulus = rng.gen_range(2u64..=param_msg_mod as u64);
+ let carry_modulus = rng.gen_range(2u64..=param_carry_mod as u64);
let modulus = msg_modulus * carry_modulus;
From 8a3312bd0bd7c717badf236d6cd7ea16197e74d8 Mon Sep 17 00:00:00 2001
From: "Mayeul@Zama" <69792125+mayeul-zama@users.noreply.github.com>
Date: Mon, 18 Mar 2024 14:50:27 +0100
Subject: [PATCH 02/12] refactor(shortint): split shortint parametrized tests
in 2 files
---
tfhe/src/shortint/server_key/tests/mod.rs | 3 +-
.../{shortint.rs => parametrized_test.rs} | 1560 +---------------
...rametrized_test_bivariate_pbs_compliant.rs | 1622 +++++++++++++++++
3 files changed, 1660 insertions(+), 1525 deletions(-)
rename tfhe/src/shortint/server_key/tests/{shortint.rs => parametrized_test.rs} (56%)
create mode 100644 tfhe/src/shortint/server_key/tests/parametrized_test_bivariate_pbs_compliant.rs
diff --git a/tfhe/src/shortint/server_key/tests/mod.rs b/tfhe/src/shortint/server_key/tests/mod.rs
index a8f569b360..21febd51a1 100644
--- a/tfhe/src/shortint/server_key/tests/mod.rs
+++ b/tfhe/src/shortint/server_key/tests/mod.rs
@@ -1,3 +1,4 @@
pub mod noise_level;
-pub mod shortint;
+pub mod parametrized_test;
+pub mod parametrized_test_bivariate_pbs_compliant;
pub mod shortint_compact_pk;
diff --git a/tfhe/src/shortint/server_key/tests/shortint.rs b/tfhe/src/shortint/server_key/tests/parametrized_test.rs
similarity index 56%
rename from tfhe/src/shortint/server_key/tests/shortint.rs
rename to tfhe/src/shortint/server_key/tests/parametrized_test.rs
index 0bca1ebe3b..d1af8d75ff 100644
--- a/tfhe/src/shortint/server_key/tests/shortint.rs
+++ b/tfhe/src/shortint/server_key/tests/parametrized_test.rs
@@ -2,7 +2,6 @@ use crate::shortint::ciphertext::{Degree, NoiseLevel};
use crate::shortint::keycache::KEY_CACHE;
use crate::shortint::parameters::*;
use crate::shortint::server_key::{LookupTableOwned, ManyLookupTableOwned};
-use paste::paste;
use rand::Rng;
/// Number of assert in randomized tests
@@ -29,9 +28,10 @@ const NB_SUB_TEST_SMART: usize = 5;
// Macro to generate tests for all parameter sets
#[cfg(not(tarpaulin))]
+#[macro_export]
macro_rules! create_parametrized_test{
($name:ident { $($param:ident),* }) => {
- paste! {
+ paste::paste! {
$(
#[test]
fn []() {
@@ -83,6 +83,7 @@ macro_rules! create_parametrized_test{
// Test against a small subset of parameters to speed up coverage tests
#[cfg(tarpaulin)]
+#[macro_export]
macro_rules! create_parametrized_test{
($name:ident { $($param:ident),* }) => {
paste! {
@@ -104,71 +105,6 @@ macro_rules! create_parametrized_test{
};
}
-//Macro to generate tests for parameters sets compatible with the bivariate pbs
-#[cfg(not(tarpaulin))]
-macro_rules! create_parametrized_test_bivariate_pbs_compliant{
- ($name:ident { $($param:ident),* }) => {
- paste! {
- $(
- #[test]
- fn []() {
- $name($param)
- }
- )*
- }
- };
- ($name:ident)=> {
- create_parametrized_test!($name
- {
- PARAM_MESSAGE_1_CARRY_1_KS_PBS,
- PARAM_MESSAGE_1_CARRY_2_KS_PBS,
- PARAM_MESSAGE_1_CARRY_3_KS_PBS,
- PARAM_MESSAGE_1_CARRY_4_KS_PBS,
- PARAM_MESSAGE_1_CARRY_5_KS_PBS,
- PARAM_MESSAGE_1_CARRY_6_KS_PBS,
- PARAM_MESSAGE_1_CARRY_7_KS_PBS,
- PARAM_MESSAGE_2_CARRY_2_KS_PBS,
- PARAM_MESSAGE_2_CARRY_3_KS_PBS,
- PARAM_MESSAGE_2_CARRY_4_KS_PBS,
- PARAM_MESSAGE_2_CARRY_5_KS_PBS,
- PARAM_MESSAGE_2_CARRY_6_KS_PBS,
- PARAM_MESSAGE_3_CARRY_3_KS_PBS,
- PARAM_MESSAGE_3_CARRY_4_KS_PBS,
- PARAM_MESSAGE_3_CARRY_5_KS_PBS,
- PARAM_MESSAGE_4_CARRY_4_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_1_CARRY_1_GROUP_2_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_2_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_3_CARRY_3_GROUP_2_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_1_CARRY_1_GROUP_3_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_3_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_3_CARRY_3_GROUP_3_KS_PBS
- });
- };
-}
-
-// Test against a small subset of parameters to speed up coverage tests
-#[cfg(tarpaulin)]
-macro_rules! create_parametrized_test_bivariate_pbs_compliant{
- ($name:ident { $($param:ident),* }) => {
- paste! {
- $(
- #[test]
- fn []() {
- $name($param)
- }
- )*
- }
- };
- ($name:ident)=> {
- create_parametrized_test!($name
- {
- PARAM_MESSAGE_2_CARRY_2_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_2_KS_PBS,
- PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_3_KS_PBS
- });
- };
-}
-
//These functions are compatible with all parameter sets.
create_parametrized_test!(shortint_encrypt_decrypt);
create_parametrized_test!(shortint_encrypt_with_message_modulus_decrypt);
@@ -244,49 +180,6 @@ fn test_shortint_public_key_smart_add_param_message_2_carry_2_ks_pbs() {
shortint_public_key_smart_add(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
}
-//These functions are compatible with some parameter sets where the carry modulus is larger than
-// the message modulus.
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitand);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitxor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_greater);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_greater_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitand);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitand);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitxor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitxor);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_greater);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_greater);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_greater_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_greater_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_less);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_less);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_less_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_less_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_less);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_less_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_greater);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_greater_or_equal);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_div);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_scalar_div);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mod);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mul_lsb);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mul_msb);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_mul_msb);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_default_mul_msb);
-create_parametrized_test_bivariate_pbs_compliant!(
- shortint_keyswitch_bivariate_programmable_bootstrap
-);
-create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less_or_equal_trivial);
-
/// test encryption and decryption with the LWE client key
fn shortint_encrypt_decrypt(param: P)
where
@@ -488,37 +381,6 @@ where
}
}
-fn shortint_keyswitch_bivariate_programmable_bootstrap
(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
- let ctxt_1 = cks.encrypt(clear_1);
- //define the lookup_table as identity
- let acc = sks.generate_lookup_table_bivariate(|x, y| (x * 2 * y) % modulus);
- // add the two ciphertexts
- let ct_res = sks.unchecked_apply_lookup_table_bivariate(&ctxt_0, &ctxt_1, &acc);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((2 * clear_0 * clear_1) % modulus, dec_res);
- }
-}
-
/// test extraction of a carry
fn shortint_carry_extract(param: P)
where
@@ -820,107 +682,6 @@ where
}
}
-/// test bitwise 'and' with the LWE server key
-fn shortint_unchecked_bitand
(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_bitand(&ctxt_0, &ctxt_1);
- assert_eq!(ct_res.degree, ctxt_0.degree.after_bitand(ctxt_1.degree));
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 & clear_1, dec_res);
- }
-}
-
-/// test bitwise 'or' with the LWE server key
-fn shortint_unchecked_bitor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_bitor(&ctxt_0, &ctxt_1);
- assert_eq!(ct_res.degree, ctxt_0.degree.after_bitor(ctxt_1.degree));
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 | clear_1, dec_res);
- }
-}
-
-/// test bitwise 'xor' with the LWE server key
-fn shortint_unchecked_bitxor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_bitxor(&ctxt_0, &ctxt_1);
- assert_eq!(ct_res.degree, ctxt_0.degree.after_bitxor(ctxt_1.degree));
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 ^ clear_1, dec_res);
- }
-}
-
/// test scalar bitwise 'xor' with the LWE server key
fn shortint_unchecked_scalar_bitxor(param: P)
where
@@ -1009,8 +770,7 @@ where
}
}
-/// test bitwise 'and' with the LWE server key
-fn shortint_smart_bitand
(param: P)
+fn shortint_smart_scalar_bitand
(param: P)
where
P: Into,
{
@@ -1024,39 +784,32 @@ where
for _ in 0..NB_TESTS {
let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
let scalar = rng.gen::() % mod_scalar;
- // encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
// add the two ciphertexts
- let ct_res = sks.smart_bitand(&mut ctxt_0, &mut ctxt_1);
+ let ct_res = sks.smart_scalar_bitand(&mut ctxt_0, clear_1 as u8);
// decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
// assert
- assert_eq!((clear_0 & clear_1) % modulus, dec_res);
+ assert_eq!(clear_0 & clear_1, dec_res);
}
}
-fn shortint_smart_scalar_bitand(param: P)
+fn shortint_default_scalar_bitand
(param: P)
where
P: Into,
{
let keys = KEY_CACHE.get_from_param(param);
let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
let mut rng = rand::thread_rng();
let modulus = cks.parameters.message_modulus().0 as u64;
@@ -1067,25 +820,22 @@ where
let clear_1 = rng.gen::() % modulus;
let scalar = rng.gen::() % mod_scalar;
+ // encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
clear_0 *= scalar as u64;
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_bitand(&mut ctxt_0, clear_1 as u8);
+ let ct_res = sks.scalar_bitand(&ctxt_0, clear_1 as u8);
- // decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
- // assert
assert_eq!(clear_0 & clear_1, dec_res);
}
}
-/// test default bitwise 'and' with the LWE server key
-fn shortint_default_bitand(param: P)
+fn shortint_smart_scalar_bitor
(param: P)
where
P: Into,
{
@@ -1099,33 +849,27 @@ where
for _ in 0..NB_TESTS {
let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
let scalar = rng.gen::() % mod_scalar;
- // encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
// add the two ciphertexts
- let ct_res = sks.bitand(&ctxt_0, &ctxt_1);
+ let ct_res = sks.smart_scalar_bitor(&mut ctxt_0, clear_1 as u8);
// decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
// assert
- assert_eq!((clear_0 & clear_1) % modulus, dec_res);
+ assert_eq!((clear_0 | clear_1) % modulus, dec_res);
}
}
-fn shortint_default_scalar_bitand(param: P)
+fn shortint_default_scalar_bitor
(param: P)
where
P: Into,
{
@@ -1148,16 +892,15 @@ where
clear_0 *= scalar as u64;
- let ct_res = sks.scalar_bitand(&ctxt_0, clear_1 as u8);
+ let ct_res = sks.scalar_bitor(&ctxt_0, clear_1 as u8);
let dec_res = cks.decrypt(&ct_res);
- assert_eq!(clear_0 & clear_1, dec_res);
+ assert_eq!((clear_0 | clear_1) % modulus, dec_res);
}
}
-/// test bitwise 'or' with the LWE server key
-fn shortint_smart_bitor(param: P)
+fn shortint_smart_scalar_bitxor
(param: P)
where
P: Into,
{
@@ -1171,39 +914,32 @@ where
for _ in 0..NB_TESTS {
let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
let scalar = rng.gen::() % mod_scalar;
- // encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
// add the two ciphertexts
- let ct_res = sks.smart_bitor(&mut ctxt_0, &mut ctxt_1);
+ let ct_res = sks.smart_scalar_bitxor(&mut ctxt_0, clear_1 as u8);
// decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
// assert
- assert_eq!((clear_0 | clear_1) % modulus, dec_res);
+ assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
}
}
-fn shortint_smart_scalar_bitor(param: P)
+fn shortint_default_scalar_bitxor
(param: P)
where
P: Into,
{
let keys = KEY_CACHE.get_from_param(param);
let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
let mut rng = rand::thread_rng();
let modulus = cks.parameters.message_modulus().0 as u64;
@@ -1214,25 +950,23 @@ where
let clear_1 = rng.gen::() % modulus;
let scalar = rng.gen::() % mod_scalar;
+ // encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
clear_0 *= scalar as u64;
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_bitor(&mut ctxt_0, clear_1 as u8);
+ let ct_res = sks.scalar_bitxor(&ctxt_0, clear_1 as u8);
- // decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
- // assert
- assert_eq!((clear_0 | clear_1) % modulus, dec_res);
+ assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
}
}
-/// test default bitwise 'or' with the LWE server key
-fn shortint_default_bitor(param: P)
+/// test LSB multiplication with the LWE server key
+fn shortint_smart_mul_lsb
(param: P)
where
P: Into,
{
@@ -1242,12 +976,11 @@ where
let mut rng = rand::thread_rng();
let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
+ for _ in 0..NB_TESTS_SMART {
+ let clear_0 = rng.gen::() % modulus;
+
+ let clear_1 = rng.gen::() % modulus;
// encryption of an integer
let mut ctxt_0 = cks.encrypt(clear_0);
@@ -1255,1155 +988,14 @@ where
// encryption of an integer
let mut ctxt_1 = cks.encrypt(clear_1);
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
// add the two ciphertexts
- let ct_res = sks.bitor(&ctxt_0, &ctxt_1);
+ let mut ct_res = sks.smart_mul_lsb(&mut ctxt_0, &mut ctxt_1);
+
+ let mut clear = clear_0 * clear_1;
- // decryption of ct_res
let dec_res = cks.decrypt(&ct_res);
- // assert
- assert_eq!((clear_0 | clear_1) % modulus, dec_res);
- }
-}
-
-fn shortint_default_scalar_bitor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
-
- clear_0 *= scalar as u64;
-
- let ct_res = sks.scalar_bitor(&ctxt_0, clear_1 as u8);
-
- let dec_res = cks.decrypt(&ct_res);
-
- assert_eq!((clear_0 | clear_1) % modulus, dec_res);
- }
-}
-
-/// test bitwise 'xor' with the LWE server key
-fn shortint_smart_bitxor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.smart_bitxor(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
- }
-}
-
-fn shortint_smart_scalar_bitxor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
-
- clear_0 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_bitxor(&mut ctxt_0, clear_1 as u8);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
- }
-}
-
-/// test default bitwise 'xor' with the LWE server key
-fn shortint_default_bitxor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.bitxor(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
- }
-}
-
-fn shortint_default_scalar_bitxor(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
-
- clear_0 *= scalar as u64;
-
- let ct_res = sks.scalar_bitxor(&ctxt_0, clear_1 as u8);
-
- let dec_res = cks.decrypt(&ct_res);
-
- assert_eq!((clear_0 ^ clear_1) % modulus, dec_res);
- }
-}
-
-/// test '>' with the LWE server key
-fn shortint_unchecked_greater(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_greater(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 > clear_1) as u64, dec_res);
- }
-}
-
-/// test '>' with the LWE server key
-fn shortint_smart_greater(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.smart_greater(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 > clear_1) as u64, dec_res);
- }
-}
-
-/// test default '>' with the LWE server key
-fn shortint_default_greater(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.greater(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 > clear_1) as u64, dec_res);
- }
-}
-
-/// test '>=' with the LWE server key
-fn shortint_unchecked_greater_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_greater_or_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 >= clear_1) as u64, dec_res);
- }
-}
-
-/// test '>=' with the LWE server key
-fn shortint_smart_greater_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 = (clear_0 * scalar as u64) % modulus;
- clear_1 = (clear_1 * scalar as u64) % modulus;
-
- // add the two ciphertexts
- let ct_res = sks.smart_greater_or_equal(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 >= clear_1) as u64, dec_res);
- }
-}
-
-/// test default '>=' with the LWE server key
-fn shortint_default_greater_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 = (clear_0 * scalar as u64) % modulus;
- clear_1 = (clear_1 * scalar as u64) % modulus;
-
- // add the two ciphertexts
- let ct_res = sks.greater_or_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 >= clear_1) as u64, dec_res);
- }
-}
-
-/// test '<' with the LWE server key
-fn shortint_unchecked_less(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_less(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 < clear_1) as u64, dec_res);
- }
-}
-
-/// test '<' with the LWE server key
-fn shortint_smart_less(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 = (clear_0 * scalar as u64) % modulus;
- clear_1 = (clear_1 * scalar as u64) % modulus;
-
- // add the two ciphertexts
- let ct_res = sks.smart_less(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 < clear_1) as u64, dec_res);
- }
-}
-
-/// test default '<' with the LWE server key
-fn shortint_default_less(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 = (clear_0 * scalar as u64) % modulus;
- clear_1 = (clear_1 * scalar as u64) % modulus;
-
- // add the two ciphertexts
- let ct_res = sks.less(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 < clear_1) as u64, dec_res);
- }
-}
-
-/// test '<=' with the LWE server key
-fn shortint_unchecked_less_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_less_or_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 <= clear_1) as u64, dec_res);
- }
-}
-
-/// test '<=' with the LWE server key
-fn shortint_unchecked_less_or_equal_trivial(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = sks.create_trivial(clear_0);
-
- // encryption of an integer
- let ctxt_1 = sks.create_trivial(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_less_or_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 <= clear_1) as u64, dec_res);
- }
-}
-
-/// test '<=' with the LWE server key
-fn shortint_smart_less_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.smart_less_or_equal(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(((clear_0 % modulus) <= (clear_1 % modulus)) as u64, dec_res);
- }
-}
-
-/// test default '<=' with the LWE server key
-fn shortint_default_less_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.less_or_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(((clear_0 % modulus) <= (clear_1 % modulus)) as u64, dec_res);
- }
-}
-
-fn shortint_unchecked_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 == clear_1) as u64, dec_res);
- }
-}
-
-/// test '==' with the LWE server key
-fn shortint_smart_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.smart_equal(&mut ctxt_0, &mut ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(((clear_0 % modulus) == (clear_1 % modulus)) as u64, dec_res);
- }
-}
-
-/// test default '==' with the LWE server key
-fn shortint_default_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
- let mod_scalar = cks.parameters.carry_modulus().0 as u8;
-
- for _ in 0..NB_TESTS {
- let mut clear_0 = rng.gen::() % modulus;
- let mut clear_1 = rng.gen::() % modulus;
- let scalar = rng.gen::() % mod_scalar;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
- sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
-
- clear_0 *= scalar as u64;
- clear_1 *= scalar as u64;
-
- // add the two ciphertexts
- let ct_res = sks.equal(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(((clear_0 % modulus) == (clear_1 % modulus)) as u64, dec_res);
- }
-}
-
-/// test '==' with the LWE server key
-fn shortint_smart_scalar_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let msg_modulus = cks.parameters.message_modulus().0 as u64;
- let modulus = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
-
- for _ in 0..NB_TESTS {
- let clear = rng.gen::() % msg_modulus;
-
- let scalar = (rng.gen::() % modulus as u16) as u8;
-
- // encryption of an integer
- let mut ctxt = cks.encrypt(clear);
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_equal(&mut ctxt, scalar);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear == scalar as u64) as u64, dec_res);
- }
-}
-
-/// test '<' with the LWE server key
-fn shortint_smart_scalar_less(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let msg_modulus = cks.parameters.message_modulus().0 as u64;
- let modulus = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
-
- for _ in 0..NB_TESTS {
- let clear = rng.gen::() % msg_modulus;
-
- let scalar = (rng.gen::() % modulus as u16) as u8;
-
- // encryption of an integer
- let mut ctxt = cks.encrypt(clear);
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_less(&mut ctxt, scalar);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear < scalar as u64) as u64, dec_res);
- }
-}
-
-/// test '<=' with the LWE server key
-fn shortint_smart_scalar_less_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let msg_modulus = cks.parameters.message_modulus().0 as u64;
- let modulus = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
-
- for _ in 0..NB_TESTS {
- let clear = rng.gen::() % msg_modulus;
-
- let scalar = (rng.gen::() % modulus as u16) as u8;
-
- // encryption of an integer
- let mut ctxt = cks.encrypt(clear);
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_less_or_equal(&mut ctxt, scalar);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear <= scalar as u64) as u64, dec_res);
- }
-}
-
-/// test '>' with the LWE server key
-fn shortint_smart_scalar_greater(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let msg_modulus = cks.parameters.message_modulus().0 as u64;
- let modulus = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
-
- for _ in 0..NB_TESTS {
- let clear = rng.gen::() % msg_modulus;
-
- let scalar = (rng.gen::() % modulus as u16) as u8;
-
- // encryption of an integer
- let mut ctxt = cks.encrypt(clear);
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_greater(&mut ctxt, scalar);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear > scalar as u64) as u64, dec_res);
- }
-}
-
-/// test '>' with the LWE server key
-fn shortint_smart_scalar_greater_or_equal(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let msg_modulus = cks.parameters.message_modulus().0 as u64;
- let modulus = (cks.parameters.message_modulus().0 * cks.parameters.carry_modulus().0) as u64;
-
- for _ in 0..NB_TESTS {
- let clear = rng.gen::() % msg_modulus;
-
- let scalar = (rng.gen::() % modulus as u16) as u8;
-
- // encryption of an integer
- let mut ctxt = cks.encrypt(clear);
-
- // add the two ciphertexts
- let ct_res = sks.smart_scalar_greater_or_equal(&mut ctxt, scalar);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear >= scalar as u64) as u64, dec_res);
- }
-}
-
-/// test division with the LWE server key
-fn shortint_unchecked_div(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- // check div by 0 result
- {
- let numerator = 1u64;
- let denominator = 0u64;
-
- let ct_num = cks.encrypt(numerator);
- let ct_denom = cks.encrypt(denominator);
- let ct_res = sks.unchecked_div(&ct_num, &ct_denom);
-
- let res = cks.decrypt(&ct_res);
- assert_eq!(res, (ct_num.message_modulus.0 - 1) as u64);
- }
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = (rng.gen::() % (modulus - 1)) + 1;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_div(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 / clear_1, dec_res);
- }
-}
-
-/// test scalar division with the LWE server key
-fn shortint_unchecked_scalar_div(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = (rng.gen::() % (modulus - 1)) + 1;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_scalar_div(&ctxt_0, clear_1 as u8);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 / clear_1, dec_res);
- }
-}
-
-/// test modulus with the LWE server key
-fn shortint_unchecked_mod(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = (rng.gen::() % (modulus - 1)) + 1;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_scalar_mod(&ctxt_0, clear_1 as u8);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear_0 % clear_1, dec_res);
- }
-}
-
-/// test LSB multiplication with the LWE server key
-fn shortint_unchecked_mul_lsb(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_mul_lsb(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 * clear_1) % modulus, dec_res);
- }
-}
-
-/// test MSB multiplication with the LWE server key
-fn shortint_unchecked_mul_msb(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.unchecked_mul_msb(&ctxt_0, &ctxt_1);
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!((clear_0 * clear_1) / modulus, dec_res);
- }
-}
-
-/// test LSB multiplication with the LWE server key
-fn shortint_smart_mul_lsb(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS_SMART {
- let clear_0 = rng.gen::() % modulus;
-
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let mut ct_res = sks.smart_mul_lsb(&mut ctxt_0, &mut ctxt_1);
-
- let mut clear = clear_0 * clear_1;
-
- let dec_res = cks.decrypt(&ct_res);
-
- assert_eq!(clear % modulus, dec_res);
+ assert_eq!(clear % modulus, dec_res);
// multiply several times to raise the degree
for _ in 0..NB_SUB_TEST_SMART {
@@ -2453,86 +1045,6 @@ where
}
}
-/// test MSB multiplication with the LWE server key
-fn shortint_smart_mul_msb(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS_SMART {
- let clear_0 = rng.gen::() % modulus;
-
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let mut ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let mut ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let mut ct_res = sks.smart_mul_msb(&mut ctxt_0, &mut ctxt_1);
-
- let mut clear = (clear_0 * clear_1) / modulus;
-
- let dec_res = cks.decrypt(&ct_res);
-
- assert_eq!(clear % modulus, dec_res);
-
- // multiply several times to raise the degree
- for _ in 0..NB_SUB_TEST_SMART {
- ct_res = sks.smart_mul_msb(&mut ct_res, &mut ctxt_0);
- clear = (clear * clear_0) / modulus;
-
- // decryption of ct_res
- let dec_res = cks.decrypt(&ct_res);
-
- // assert
- assert_eq!(clear % modulus, dec_res);
- }
- }
-}
-
-/// test default MSB multiplication with the LWE server key
-fn shortint_default_mul_msb(param: P)
-where
- P: Into,
-{
- let keys = KEY_CACHE.get_from_param(param);
- let (cks, sks) = (keys.client_key(), keys.server_key());
- //RNG
- let mut rng = rand::thread_rng();
-
- let modulus = cks.parameters.message_modulus().0 as u64;
-
- for _ in 0..NB_TESTS {
- let clear_0 = rng.gen::() % modulus;
-
- let clear_1 = rng.gen::() % modulus;
-
- // encryption of an integer
- let ctxt_0 = cks.encrypt(clear_0);
-
- // encryption of an integer
- let ctxt_1 = cks.encrypt(clear_1);
-
- // add the two ciphertexts
- let ct_res = sks.mul_msb(&ctxt_0, &ctxt_1);
-
- let clear = (clear_0 * clear_1) / modulus;
-
- let dec_res = cks.decrypt(&ct_res);
-
- assert_eq!(clear % modulus, dec_res);
- }
-}
-
/// test unchecked negation
fn shortint_unchecked_neg(param: P)
where
@@ -2905,7 +1417,7 @@ where
}
}
-/// test default smart scalar multiplication with the LWE server key
+/// test default scalar multiplication with the LWE server key
fn shortint_default_scalar_mul
(param: P)
where
P: Into,
diff --git a/tfhe/src/shortint/server_key/tests/parametrized_test_bivariate_pbs_compliant.rs b/tfhe/src/shortint/server_key/tests/parametrized_test_bivariate_pbs_compliant.rs
new file mode 100644
index 0000000000..ce61a1ed2c
--- /dev/null
+++ b/tfhe/src/shortint/server_key/tests/parametrized_test_bivariate_pbs_compliant.rs
@@ -0,0 +1,1622 @@
+use crate::create_parametrized_test;
+use crate::shortint::keycache::KEY_CACHE;
+use crate::shortint::parameters::*;
+use rand::Rng;
+
+/// Number of assert in randomized tests
+#[cfg(not(tarpaulin))]
+const NB_TESTS: usize = 200;
+/// Number of iterations in randomized tests for smart operations
+#[cfg(not(tarpaulin))]
+const NB_TESTS_SMART: usize = 10;
+/// Number of sub tests used to increase degree of ciphertexts
+#[cfg(not(tarpaulin))]
+const NB_SUB_TEST_SMART: usize = 40;
+
+// Use lower numbers for coverage to ensure fast tests to counter balance slowdown due to code
+// instrumentation
+#[cfg(tarpaulin)]
+const NB_TESTS: usize = 1;
+/// Number of iterations in randomized tests for smart operations
+#[cfg(tarpaulin)]
+const NB_TESTS_SMART: usize = 1;
+// This constant is tailored to trigger a message extract during operation processing.
+// It's applicable for PARAM_MESSAGE_2_CARRY_2_KS_PBS parameters set.
+#[cfg(tarpaulin)]
+const NB_SUB_TEST_SMART: usize = 5;
+
+//Macro to generate tests for parameters sets compatible with the bivariate pbs
+#[cfg(not(tarpaulin))]
+macro_rules! create_parametrized_test_bivariate_pbs_compliant{
+ ($name:ident { $($param:ident),* }) => {
+ paste! {
+ $(
+ #[test]
+ fn []() {
+ $name($param)
+ }
+ )*
+ }
+ };
+ ($name:ident)=> {
+ create_parametrized_test!($name
+ {
+ PARAM_MESSAGE_1_CARRY_1_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_2_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_3_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_4_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_5_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_6_KS_PBS,
+ PARAM_MESSAGE_1_CARRY_7_KS_PBS,
+ PARAM_MESSAGE_2_CARRY_2_KS_PBS,
+ PARAM_MESSAGE_2_CARRY_3_KS_PBS,
+ PARAM_MESSAGE_2_CARRY_4_KS_PBS,
+ PARAM_MESSAGE_2_CARRY_5_KS_PBS,
+ PARAM_MESSAGE_2_CARRY_6_KS_PBS,
+ PARAM_MESSAGE_3_CARRY_3_KS_PBS,
+ PARAM_MESSAGE_3_CARRY_4_KS_PBS,
+ PARAM_MESSAGE_3_CARRY_5_KS_PBS,
+ PARAM_MESSAGE_4_CARRY_4_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_1_CARRY_1_GROUP_2_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_2_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_3_CARRY_3_GROUP_2_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_1_CARRY_1_GROUP_3_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_3_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_3_CARRY_3_GROUP_3_KS_PBS
+ });
+ };
+}
+
+// Test against a small subset of parameters to speed up coverage tests
+#[cfg(tarpaulin)]
+macro_rules! create_parametrized_test_bivariate_pbs_compliant{
+ ($name:ident { $($param:ident),* }) => {
+ paste! {
+ $(
+ #[test]
+ fn []() {
+ $name($param)
+ }
+ )*
+ }
+ };
+ ($name:ident)=> {
+ create_parametrized_test!($name
+ {
+ PARAM_MESSAGE_2_CARRY_2_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_2_KS_PBS,
+ PARAM_MULTI_BIT_MESSAGE_2_CARRY_2_GROUP_3_KS_PBS
+ });
+ };
+}
+
+// Public key tests are limited to small parameter sets to avoid blowing up memory and large testing
+// times. Compressed keygen takes 20 minutes for params 2_2 and for encryption as well.
+// 2_2 uncompressed keys take ~2 GB and 3_3 about ~34 GB, hence why we stop at 2_2.
+#[cfg(not(tarpaulin))]
+#[test]
+fn test_shortint_compressed_public_key_smart_add_param_message_1_carry_1_ks_pbs() {
+ shortint_compressed_public_key_smart_add(PARAM_MESSAGE_1_CARRY_1_KS_PBS);
+}
+
+#[cfg(not(tarpaulin))]
+#[test]
+fn test_shortint_public_key_smart_add_param_message_1_carry_1_ks_pbs() {
+ shortint_public_key_smart_add(PARAM_MESSAGE_1_CARRY_1_KS_PBS);
+}
+
+#[cfg(not(tarpaulin))]
+#[test]
+fn test_shortint_public_key_smart_add_param_message_2_carry_2_ks_pbs() {
+ shortint_public_key_smart_add(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
+}
+
+//These functions are compatible with some parameter sets where the carry modulus is larger than
+// the message modulus.
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitand);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_bitxor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_greater);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_greater_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitand);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitand);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_bitxor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_bitxor);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_greater);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_greater);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_greater_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_greater_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_less);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_less);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_less_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_less_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_less);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_less_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_greater);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_scalar_greater_or_equal);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_div);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_scalar_div);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mod);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mul_lsb);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_mul_msb);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_smart_mul_msb);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_default_mul_msb);
+create_parametrized_test_bivariate_pbs_compliant!(
+ shortint_keyswitch_bivariate_programmable_bootstrap
+);
+create_parametrized_test_bivariate_pbs_compliant!(shortint_unchecked_less_or_equal_trivial);
+
+fn shortint_keyswitch_bivariate_programmable_bootstrap(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS {
+ let clear_0 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let ctxt_0 = cks.encrypt(clear_0);
+ let ctxt_1 = cks.encrypt(clear_1);
+ //define the lookup_table as identity
+ let acc = sks.generate_lookup_table_bivariate(|x, y| (x * 2 * y) % modulus);
+ // add the two ciphertexts
+ let ct_res = sks.unchecked_apply_lookup_table_bivariate(&ctxt_0, &ctxt_1, &acc);
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!((2 * clear_0 * clear_1) % modulus, dec_res);
+ }
+}
+
+/// test addition with the LWE server key using the a public key for encryption
+fn shortint_compressed_public_key_smart_add(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ let pk = crate::shortint::CompressedPublicKey::new(cks);
+
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS_SMART {
+ let clear_0 = rng.gen::() % modulus;
+
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let mut ctxt_0 = pk.encrypt(clear_0);
+
+ // encryption of an integer
+ let mut ctxt_1 = pk.encrypt(clear_1);
+
+ // add the two ciphertexts
+ let mut ct_res = sks.smart_add(&mut ctxt_0, &mut ctxt_1);
+ let mut clear = clear_0 + clear_1;
+
+ // add multiple times to raise the degree and test the smart operation
+ for _ in 0..NB_SUB_TEST_SMART {
+ ct_res = sks.smart_add(&mut ct_res, &mut ctxt_0);
+ clear += clear_0;
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!(clear % modulus, dec_res);
+ }
+ }
+}
+
+/// test addition with the LWE server key using the a public key for encryption
+fn shortint_public_key_smart_add(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ let pk = crate::shortint::PublicKey::new(cks);
+
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS_SMART {
+ let clear_0 = rng.gen::() % modulus;
+
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let mut ctxt_0 = pk.encrypt(clear_0);
+
+ // encryption of an integer
+ let mut ctxt_1 = pk.encrypt(clear_1);
+
+ // add the two ciphertexts
+ let mut ct_res = sks.smart_add(&mut ctxt_0, &mut ctxt_1);
+ let mut clear = clear_0 + clear_1;
+
+ // add multiple times to raise the degree and test the smart operation
+ for _ in 0..NB_SUB_TEST_SMART {
+ ct_res = sks.smart_add(&mut ct_res, &mut ctxt_0);
+ clear += clear_0;
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!(clear % modulus, dec_res);
+ }
+ }
+}
+
+/// test bitwise 'and' with the LWE server key
+fn shortint_unchecked_bitand(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS {
+ let clear_0 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let ctxt_0 = cks.encrypt(clear_0);
+
+ // encryption of an integer
+ let ctxt_1 = cks.encrypt(clear_1);
+
+ // add the two ciphertexts
+ let ct_res = sks.unchecked_bitand(&ctxt_0, &ctxt_1);
+ assert_eq!(ct_res.degree, ctxt_0.degree.after_bitand(ctxt_1.degree));
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!(clear_0 & clear_1, dec_res);
+ }
+}
+
+/// test bitwise 'or' with the LWE server key
+fn shortint_unchecked_bitor(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS {
+ let clear_0 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let ctxt_0 = cks.encrypt(clear_0);
+
+ // encryption of an integer
+ let ctxt_1 = cks.encrypt(clear_1);
+
+ // add the two ciphertexts
+ let ct_res = sks.unchecked_bitor(&ctxt_0, &ctxt_1);
+ assert_eq!(ct_res.degree, ctxt_0.degree.after_bitor(ctxt_1.degree));
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!(clear_0 | clear_1, dec_res);
+ }
+}
+
+/// test bitwise 'xor' with the LWE server key
+fn shortint_unchecked_bitxor(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+
+ for _ in 0..NB_TESTS {
+ let clear_0 = rng.gen::() % modulus;
+ let clear_1 = rng.gen::() % modulus;
+
+ // encryption of an integer
+ let ctxt_0 = cks.encrypt(clear_0);
+
+ // encryption of an integer
+ let ctxt_1 = cks.encrypt(clear_1);
+
+ // add the two ciphertexts
+ let ct_res = sks.unchecked_bitxor(&ctxt_0, &ctxt_1);
+ assert_eq!(ct_res.degree, ctxt_0.degree.after_bitxor(ctxt_1.degree));
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!(clear_0 ^ clear_1, dec_res);
+ }
+}
+
+/// test bitwise 'and' with the LWE server key
+fn shortint_smart_bitand(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+ let mod_scalar = cks.parameters.carry_modulus().0 as u8;
+
+ for _ in 0..NB_TESTS {
+ let mut clear_0 = rng.gen::() % modulus;
+ let mut clear_1 = rng.gen::() % modulus;
+ let scalar = rng.gen::() % mod_scalar;
+
+ // encryption of an integer
+ let mut ctxt_0 = cks.encrypt(clear_0);
+
+ // encryption of an integer
+ let mut ctxt_1 = cks.encrypt(clear_1);
+
+ sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
+ sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
+
+ clear_0 *= scalar as u64;
+ clear_1 *= scalar as u64;
+
+ // add the two ciphertexts
+ let ct_res = sks.smart_bitand(&mut ctxt_0, &mut ctxt_1);
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!((clear_0 & clear_1) % modulus, dec_res);
+ }
+}
+
+/// test default bitwise 'and' with the LWE server key
+fn shortint_default_bitand(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+ let mod_scalar = cks.parameters.carry_modulus().0 as u8;
+
+ for _ in 0..NB_TESTS {
+ let mut clear_0 = rng.gen::() % modulus;
+ let mut clear_1 = rng.gen::() % modulus;
+ let scalar = rng.gen::() % mod_scalar;
+
+ // encryption of an integer
+ let mut ctxt_0 = cks.encrypt(clear_0);
+
+ // encryption of an integer
+ let mut ctxt_1 = cks.encrypt(clear_1);
+
+ sks.unchecked_scalar_mul_assign(&mut ctxt_0, scalar);
+ sks.unchecked_scalar_mul_assign(&mut ctxt_1, scalar);
+
+ clear_0 *= scalar as u64;
+ clear_1 *= scalar as u64;
+
+ // add the two ciphertexts
+ let ct_res = sks.bitand(&ctxt_0, &ctxt_1);
+
+ // decryption of ct_res
+ let dec_res = cks.decrypt(&ct_res);
+
+ // assert
+ assert_eq!((clear_0 & clear_1) % modulus, dec_res);
+ }
+}
+
+/// test bitwise 'or' with the LWE server key
+fn shortint_smart_bitor(param: P)
+where
+ P: Into,
+{
+ let keys = KEY_CACHE.get_from_param(param);
+ let (cks, sks) = (keys.client_key(), keys.server_key());
+ //RNG
+ let mut rng = rand::thread_rng();
+
+ let modulus = cks.parameters.message_modulus().0 as u64;
+ let mod_scalar = cks.parameters.carry_modulus().0 as u8;
+
+ for _ in 0..NB_TESTS {
+ let mut clear_0 = rng.gen::() % modulus;
+ let mut clear_1 = rng.gen::() % modulus;
+ let scalar = rng.gen::