feat(typed_api): plug choice of big/small ciphertext

This commit is contained in:
tmontaigu
2023-03-30 14:14:06 +02:00
parent 3bc1536fa6
commit d7a4e87efb
39 changed files with 723 additions and 527 deletions

View File

@@ -205,6 +205,11 @@ test_integer: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --release \
--features=$(TARGET_ARCH_FEATURE),integer,internal-keycache -p tfhe -- integer::
.PHONY: test_typed_api # Run all the tests for typed_api
test_typed_api: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --release \
--features=$(TARGET_ARCH_FEATURE),boolean,shortint,integer,internal-keycache -p tfhe -- typed_api::
.PHONY: test_user_doc # Run tests from the .md documentation
test_user_doc: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --release --doc \

View File

@@ -61,8 +61,8 @@ fn main() {
let num_block = 4;
let (client_key, server_key) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_block);
let msg1 = 128;
let msg2 = 13;
let msg1 = 128u64;
let msg2 = 13u64;
// We use the client key to encrypt two messages:
let ct_1 = client_key.encrypt(msg1);
@@ -98,7 +98,7 @@ fn main() {
let ct_3 = server_key.unchecked_add(&ct_1, &ct_2);
// We use the client key to decrypt the output of the circuit:
let output = client_key.decrypt(&ct_3);
let output: u64 = client_key.decrypt(&ct_3);
assert_eq!(output, (msg1 + msg2) % modulus);
}

View File

@@ -40,7 +40,7 @@ fn main() {
let ct_res = wopbs_key.keyswitch_to_pbs_params(&ct_res);
// decryption
let res = cks.decrypt(&ct_res);
let res: u64 = cks.decrypt(&ct_res);
let clear = f(msg) % modulus;
assert_eq!(res, clear);

View File

@@ -15,10 +15,10 @@ fn main() {
let num_block = 4;
let (client_key, server_key) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_block);
let msg1 = 12;
let msg2 = 11;
let msg3 = 9;
let scalar = 3;
let msg1 = 12u64;
let msg2 = 11u64;
let msg3 = 9u64;
let scalar = 3u64;
// message_modulus^vec_length
let modulus = client_key.parameters().message_modulus.0.pow(num_block as u32) as u64;
@@ -35,7 +35,7 @@ fn main() {
server_key.unchecked_add_assign(&mut ct_1, &ct_3);
// We use the client key to decrypt the output of the circuit:
let output = client_key.decrypt(&ct_1);
let output: u64 = client_key.decrypt(&ct_1);
// The carry buffer has been overflowed, the result is not correct
assert_ne!(output, ((msg1 * scalar as u64 - msg2) + msg3) % modulus as u64);
}
@@ -54,10 +54,10 @@ fn main() {
let num_block = 2;
let (client_key, server_key) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_block);
let msg1 = 12;
let msg2 = 11;
let msg3 = 9;
let scalar = 3;
let msg1 = 12u64;
let msg2 = 11u64;
let msg3 = 9u64;
let scalar = 3u64;
// message_modulus^vec_length
let modulus = client_key.parameters().message_modulus.0.pow(num_block as u32) as u64;
@@ -75,7 +75,7 @@ fn main() {
// We use the client key to decrypt the output of the circuit:
// Only the scalar multiplication could be done
let output = client_key.decrypt(&ct_1);
let output: u64 = client_key.decrypt(&ct_1);
assert_eq!(output, (msg1 * scalar) % modulus as u64);
}
```
@@ -114,7 +114,7 @@ fn main() {
server_key.smart_add_assign(&mut ct_1, &mut ct_3);
// We use the client key to decrypt the output of the circuit:
let output = client_key.decrypt(&ct_1);
let output: u64 = client_key.decrypt(&ct_1);
assert_eq!(output, ((msg1 * scalar as u64 - msg2) + msg3) % modulus as u64);
}
```
```

View File

@@ -53,7 +53,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let serialized_result = server_function(&serialized_data)?;
let result: RadixCiphertextBig = bincode::deserialize(&serialized_result)?;
let output = client_key.decrypt(&result);
let output: u64 = client_key.decrypt(&result);
assert_eq!(output, (msg1 + msg2) % modulus);
Ok(())
}

View File

@@ -14,8 +14,8 @@
//! homomorphically.
//!
//! ```rust
//! use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
//! use tfhe::integer::gen_keys_radix;
//! use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
//!
//! //4 blocks for the radix decomposition
//! let number_of_blocks = 4;

View File

@@ -32,7 +32,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_add(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 + msg2);
/// ```
pub fn unchecked_add<PBSOrder: PBSOrderMarker>(
@@ -68,7 +68,7 @@ impl ServerKey {
/// sks.unchecked_add_assign(&mut ct1, &ct2);
///
/// // Decrypt:
/// let dec_ct1 = cks.decrypt(&ct1);
/// let dec_ct1: u64 = cks.decrypt(&ct1);
/// assert_eq!(dec_ct1, msg1 + msg2);
/// ```
pub fn unchecked_add_assign<PBSOrder: PBSOrderMarker>(
@@ -93,8 +93,8 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg1 = 46;
/// let msg2 = 87;
/// let msg1 = 46u64;
/// let msg2 = 87u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -144,7 +144,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg1 + msg2, clear);
/// }
/// }
@@ -190,7 +190,7 @@ impl ServerKey {
///
/// assert!(res.is_ok());
///
/// let clear = cks.decrypt(&ct1);
/// let clear: u64 = cks.decrypt(&ct1);
/// assert_eq!(msg1 + msg2, clear);
/// ```
pub fn checked_add_assign<PBSOrder: PBSOrderMarker>(
@@ -228,7 +228,7 @@ impl ServerKey {
/// let ct_res = sks.smart_add(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 + msg2);
/// ```
pub fn smart_add<PBSOrder: PBSOrderMarker>(

View File

@@ -21,8 +21,8 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 201;
/// let msg2 = 1;
/// let msg1 = 201u64;
/// let msg2 = 1u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -31,7 +31,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_bitand(&ct1, &ct2);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec, msg1 & msg2);
/// ```
pub fn unchecked_bitand<PBSOrder: PBSOrderMarker>(
@@ -67,8 +67,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 46;
/// let msg2 = 87;
/// let msg1 = 46u64;
/// let msg2 = 87u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -120,7 +120,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg1 & msg2, clear);
/// }
/// }
@@ -163,7 +163,7 @@ impl ServerKey {
///
/// assert!(res.is_ok());
///
/// let clear = cks.decrypt(&ct1);
/// let clear: u64 = cks.decrypt(&ct1);
/// assert_eq!(msg1 & msg2, clear);
/// ```
pub fn checked_bitand_assign<PBSOrder: PBSOrderMarker>(
@@ -201,7 +201,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitand(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 & msg2);
/// ```
pub fn smart_bitand<PBSOrder: PBSOrderMarker>(
@@ -255,7 +255,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_bitor(&ct1, &ct2);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec, msg1 | msg2);
/// ```
pub fn unchecked_bitor<PBSOrder: PBSOrderMarker>(
@@ -306,7 +306,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg1 | msg2, clear);
/// }
/// }
@@ -350,7 +350,7 @@ impl ServerKey {
///
/// assert!(res.is_ok());
///
/// let clear = cks.decrypt(&ct1);
/// let clear: u64 = cks.decrypt(&ct1);
/// assert_eq!(msg1 | msg2, clear);
/// ```
pub fn checked_bitor_assign<PBSOrder: PBSOrderMarker>(
@@ -388,7 +388,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 | msg2);
/// ```
pub fn smart_bitor<PBSOrder: PBSOrderMarker>(
@@ -442,7 +442,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_bitxor(&ct1, &ct2);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg1 ^ msg2, dec);
/// ```
pub fn unchecked_bitxor<PBSOrder: PBSOrderMarker>(
@@ -493,7 +493,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg1 ^ msg2, clear);
/// }
/// }
@@ -537,7 +537,7 @@ impl ServerKey {
///
/// assert!(res.is_ok());
///
/// let clear = cks.decrypt(&ct1);
/// let clear: u64 = cks.decrypt(&ct1);
/// assert_eq!(msg1 ^ msg2, clear);
/// ```
pub fn checked_bitxor_assign<PBSOrder: PBSOrderMarker>(
@@ -575,7 +575,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitxor(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 ^ msg2);
/// ```
pub fn smart_bitxor<PBSOrder: PBSOrderMarker>(

View File

@@ -22,8 +22,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -31,7 +31,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_eq(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 == msg2));
/// ```
pub fn unchecked_eq<PBSOrder: PBSOrderMarker>(
@@ -59,8 +59,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -68,7 +68,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_gt(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 > msg2));
/// ```
pub fn unchecked_gt<PBSOrder: PBSOrderMarker>(
@@ -96,8 +96,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 97;
/// let msg2 = 97;
/// let msg1 = 97u64;
/// let msg2 = 97u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -105,7 +105,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_ge(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 >= msg2));
/// ```
pub fn unchecked_ge<PBSOrder: PBSOrderMarker>(
@@ -133,8 +133,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 237;
/// let msg2 = 23;
/// let msg1 = 237u64;
/// let msg2 = 23u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -142,7 +142,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_lt(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 < msg2));
/// ```
pub fn unchecked_lt<PBSOrder: PBSOrderMarker>(
@@ -170,8 +170,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 237;
/// let msg2 = 23;
/// let msg1 = 237u64;
/// let msg2 = 23u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -179,7 +179,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_le(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 < msg2));
/// ```
pub fn unchecked_le<PBSOrder: PBSOrderMarker>(
@@ -206,8 +206,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 237;
/// let msg2 = 23;
/// let msg1 = 237u64;
/// let msg2 = 23u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -215,7 +215,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_max(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, std::cmp::max(msg1, msg2));
/// ```
pub fn unchecked_max<PBSOrder: PBSOrderMarker>(
@@ -242,8 +242,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 237;
/// let msg2 = 23;
/// let msg1 = 237u64;
/// let msg2 = 23u64;
///
/// let ct1 = cks.encrypt(msg1);
/// let ct2 = cks.encrypt(msg2);
@@ -251,7 +251,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_min(&ct1, &ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, std::cmp::min(msg1, msg2));
/// ```
pub fn unchecked_min<PBSOrder: PBSOrderMarker>(
@@ -277,8 +277,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -286,7 +286,7 @@ impl ServerKey {
/// let ct_res = sks.smart_eq(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 == msg2));
/// ```
pub fn smart_eq<PBSOrder: PBSOrderMarker>(
@@ -312,8 +312,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -321,7 +321,7 @@ impl ServerKey {
/// let ct_res = sks.smart_gt(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 > msg2));
/// ```
pub fn smart_gt<PBSOrder: PBSOrderMarker>(
@@ -347,8 +347,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -356,7 +356,7 @@ impl ServerKey {
/// let ct_res = sks.smart_gt(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 >= msg2));
/// ```
pub fn smart_ge<PBSOrder: PBSOrderMarker>(
@@ -382,8 +382,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -391,7 +391,7 @@ impl ServerKey {
/// let ct_res = sks.smart_lt(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 < msg2));
/// ```
pub fn smart_lt<PBSOrder: PBSOrderMarker>(
@@ -417,8 +417,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -426,7 +426,7 @@ impl ServerKey {
/// let ct_res = sks.smart_le(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, u64::from(msg1 <= msg2));
/// ```
pub fn smart_le<PBSOrder: PBSOrderMarker>(
@@ -452,8 +452,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -461,7 +461,7 @@ impl ServerKey {
/// let ct_res = sks.smart_max(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, std::cmp::max(msg1, msg2));
/// ```
pub fn smart_max<PBSOrder: PBSOrderMarker>(
@@ -487,8 +487,8 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg1 = 14;
/// let msg2 = 97;
/// let msg1 = 14u64;
/// let msg2 = 97u64;
///
/// let mut ct1 = cks.encrypt(msg1);
/// let mut ct2 = cks.encrypt(msg2);
@@ -496,7 +496,7 @@ impl ServerKey {
/// let ct_res = sks.smart_min(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, std::cmp::min(msg1, msg2));
/// ```
pub fn smart_min<PBSOrder: PBSOrderMarker>(

View File

@@ -34,7 +34,7 @@ impl ServerKey {
/// let ctxt: RadixCiphertextBig = sks.create_trivial_zero_radix(num_blocks);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ctxt);
/// let dec: u64 = cks.decrypt(&ctxt);
/// assert_eq!(0, dec);
/// ```
pub fn create_trivial_zero_radix<PBSOrder: PBSOrderMarker>(
@@ -62,7 +62,7 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg = 7;
/// let msg = 7u64;
///
/// let ct1 = cks.encrypt(msg);
/// let ct2 = cks.encrypt(msg);
@@ -72,7 +72,7 @@ impl ServerKey {
/// sks.propagate(&mut ct_res, 0);
///
/// // Decrypt one block:
/// let res = cks.decrypt_one_block(&ct_res.blocks()[1]);
/// let res: u64 = cks.decrypt_one_block(&ct_res.blocks()[1]);
/// assert_eq!(3, res);
/// ```
pub fn propagate<PBSOrder: PBSOrderMarker>(
@@ -114,7 +114,7 @@ impl ServerKey {
/// sks.full_propagate(&mut ct_res);
///
/// // Decrypt:
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + msg, res);
/// ```
pub fn full_propagate<PBSOrder: PBSOrderMarker>(&self, ctxt: &mut RadixCiphertext<PBSOrder>) {

View File

@@ -32,7 +32,7 @@ impl ServerKey {
/// sks.unchecked_block_mul_assign(&mut ct_left, &ct_right, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_left);
/// let res: u64 = cks.decrypt(&ct_left);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_block_mul_assign<PBSOrder: PBSOrderMarker>(
@@ -73,7 +73,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_block_mul(&ct_left, &ct_right, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_block_mul<PBSOrder: PBSOrderMarker>(
@@ -127,7 +127,7 @@ impl ServerKey {
/// let ct_res = sks.smart_block_mul(&mut ctxt_1, &ctxt_2, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn smart_block_mul<PBSOrder: PBSOrderMarker>(
@@ -194,7 +194,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_mul(&mut ctxt_1, &ctxt_2);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_mul_assign<PBSOrder: PBSOrderMarker>(
@@ -251,7 +251,7 @@ impl ServerKey {
/// // Compute homomorphically a multiplication
/// let ct_res = sks.smart_mul(&mut ctxt_1, &mut ctxt_2);
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn smart_mul_assign<PBSOrder: PBSOrderMarker>(

View File

@@ -24,7 +24,7 @@ impl ServerKey {
/// let modulus = 1 << 8;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 159;
/// let msg = 159u64;
///
/// // Encrypt a message
/// let mut ctxt = cks.encrypt(msg);
@@ -33,7 +33,7 @@ impl ServerKey {
/// sks.unchecked_neg_assign(&mut ctxt);
///
/// // Decrypt
/// let dec = cks.decrypt(&ctxt);
/// let dec: u64 = cks.decrypt(&ctxt);
/// assert_eq!(modulus - msg, dec);
/// ```
pub fn unchecked_neg<PBSOrder: PBSOrderMarker>(
@@ -87,7 +87,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 2;
/// let msg = 2u64;
///
/// // Encrypt a message
/// let ctxt = cks.encrypt(msg);
@@ -126,7 +126,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 1;
/// let msg = 1u64;
///
/// // Encrypt a message
/// let ctxt = cks.encrypt(msg);
@@ -137,7 +137,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(255, clear);
/// }
/// }
@@ -180,7 +180,7 @@ impl ServerKey {
/// // Compute homomorphically a negation:
/// sks.checked_neg_assign(&mut ct);
///
/// let clear_res = cks.decrypt(&ct);
/// let clear_res: u64 = cks.decrypt(&ct);
/// assert_eq!(clear_res, (modulus - msg));
/// ```
pub fn checked_neg_assign<PBSOrder: PBSOrderMarker>(
@@ -210,7 +210,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 1;
/// let msg = 1u64;
///
/// // Encrypt two messages:
/// let mut ctxt = cks.encrypt(msg);
@@ -219,7 +219,7 @@ impl ServerKey {
/// let ct_res = sks.smart_neg(&mut ctxt);
///
/// // Decrypt
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(255, dec);
/// ```
pub fn smart_neg<PBSOrder: PBSOrderMarker>(

View File

@@ -31,7 +31,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_add(&ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + scalar, dec);
/// ```
pub fn unchecked_scalar_add<PBSOrder: PBSOrderMarker>(
@@ -84,7 +84,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 2;
/// let msg = 2u64;
/// let scalar = 40;
///
/// // Encrypt two messages:
@@ -146,7 +146,7 @@ impl ServerKey {
/// let ct_res = sks.checked_scalar_add(&mut ct, scalar)?;
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + scalar, dec);
/// # Ok(())
/// # }
@@ -203,7 +203,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_add(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + scalar, dec);
/// ```
pub fn smart_scalar_add<PBSOrder: PBSOrderMarker>(
@@ -243,7 +243,7 @@ impl ServerKey {
/// sks.smart_scalar_add_assign(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg + scalar, dec);
/// ```
pub fn smart_scalar_add_assign<PBSOrder: PBSOrderMarker>(

View File

@@ -31,7 +31,7 @@ impl ServerKey {
/// // Compute homomorphically a scalar multiplication:
/// let ct_res = sks.unchecked_small_scalar_mul(&ct, scalar);
///
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(scalar * msg, clear);
/// ```
pub fn unchecked_small_scalar_mul<PBSOrder: PBSOrderMarker>(
@@ -67,7 +67,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 25;
/// let msg = 25u64;
/// let scalar1 = 3;
///
/// let ct = cks.encrypt(msg);
@@ -121,7 +121,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg * scalar, clear);
/// }
/// }
@@ -167,7 +167,7 @@ impl ServerKey {
/// // Compute homomorphically a scalar multiplication:
/// sks.checked_small_scalar_mul_assign(&mut ct, scalar);
///
/// let clear_res = cks.decrypt(&ct);
/// let clear_res: u64 = cks.decrypt(&ct);
/// assert_eq!(clear_res, msg * scalar);
/// ```
pub fn checked_small_scalar_mul_assign<PBSOrder: PBSOrderMarker>(
@@ -212,7 +212,7 @@ impl ServerKey {
/// let ct_res = sks.smart_small_scalar_mul(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_small_scalar_mul<PBSOrder: PBSOrderMarker>(
@@ -254,7 +254,7 @@ impl ServerKey {
/// sks.smart_small_scalar_mul_assign(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct);
/// let clear: u64 = cks.decrypt(&ct);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_small_scalar_mul_assign<PBSOrder: PBSOrderMarker>(
@@ -278,7 +278,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 1;
/// let msg = 1u64;
/// let power = 2;
///
/// let ct = cks.encrypt(msg);
@@ -287,7 +287,7 @@ impl ServerKey {
/// let ct_res = sks.blockshift(&ct, power);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(16, clear);
/// ```
pub fn blockshift<PBSOrder: PBSOrderMarker>(
@@ -331,7 +331,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_mul(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_scalar_mul<PBSOrder: PBSOrderMarker>(

View File

@@ -31,7 +31,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_sub(&ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg - scalar, dec);
/// ```
pub fn unchecked_scalar_sub<PBSOrder: PBSOrderMarker>(
@@ -87,7 +87,7 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg = 40;
/// let msg = 40u64;
/// let scalar = 2;
///
/// let ct1 = cks.encrypt(msg);
@@ -155,7 +155,7 @@ impl ServerKey {
/// let ct_res = sks.checked_scalar_sub(&ct, scalar)?;
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg - scalar, dec);
/// # Ok(())
/// # }
@@ -197,7 +197,7 @@ impl ServerKey {
/// sks.checked_scalar_sub_assign(&mut ct, scalar)?;
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg - scalar, dec);
/// # Ok(())
/// # }
@@ -236,7 +236,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_sub(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg - scalar, dec);
/// ```
pub fn smart_scalar_sub<PBSOrder: PBSOrderMarker>(

View File

@@ -28,7 +28,7 @@ impl ServerKey {
/// let div = cks.parameters().message_modulus.0.pow(shift as u32) as u64;
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg / div, clear);
/// ```
pub fn blockshift_right<PBSOrder: PBSOrderMarker>(
@@ -81,7 +81,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_right_shift(&ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg >> shift, dec);
/// ```
pub fn unchecked_scalar_right_shift<PBSOrder: PBSOrderMarker>(
@@ -117,7 +117,7 @@ impl ServerKey {
/// sks.unchecked_scalar_right_shift_assign(&mut ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg >> shift, dec);
/// ```
pub fn unchecked_scalar_right_shift_assign<PBSOrder: PBSOrderMarker>(
@@ -186,7 +186,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_left_shift(&ct1, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg << shift, dec);
/// ```
pub fn unchecked_scalar_left_shift<PBSOrder: PBSOrderMarker>(
@@ -222,7 +222,7 @@ impl ServerKey {
/// sks.unchecked_scalar_left_shift_assign(&mut ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg << shift, dec);
/// ```
pub fn unchecked_scalar_left_shift_assign<PBSOrder: PBSOrderMarker>(

View File

@@ -32,7 +32,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_sub(&ctxt_1, &ctxt_2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg_1 - msg_2);
/// ```
pub fn unchecked_sub<PBSOrder: PBSOrderMarker>(
@@ -73,7 +73,7 @@ impl ServerKey {
/// sks.unchecked_sub_assign(&mut ctxt_1, &ctxt_2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ctxt_1);
/// let dec_result: u64 = cks.decrypt(&ctxt_1);
/// assert_eq!(dec_result, msg_1 - msg_2);
/// ```
pub fn unchecked_sub_assign<PBSOrder: PBSOrderMarker>(
@@ -97,8 +97,8 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg_1 = 182;
/// let msg_2 = 120;
/// let msg_1 = 182u64;
/// let msg_2 = 120u64;
///
/// // Encrypt two messages:
/// let ctxt_1 = cks.encrypt(msg_1);
@@ -139,7 +139,7 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg = 1;
/// let msg = 1u64;
///
/// // Encrypt two messages:
/// let ctxt_1 = cks.encrypt(msg);
@@ -151,7 +151,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(0, clear);
/// }
/// }
@@ -197,7 +197,7 @@ impl ServerKey {
///
/// assert!(res.is_ok());
///
/// let clear = cks.decrypt(&ct1);
/// let clear: u64 = cks.decrypt(&ct1);
/// assert_eq!(msg1.wrapping_sub(msg2) as u64, clear);
/// ```
pub fn checked_sub_assign<PBSOrder: PBSOrderMarker>(
@@ -236,7 +236,7 @@ impl ServerKey {
/// let ct_res = sks.smart_sub(&mut ctxt_1, &mut ctxt_2);
///
/// // Decrypt:
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
/// ```
pub fn smart_sub<PBSOrder: PBSOrderMarker>(
@@ -284,7 +284,7 @@ impl ServerKey {
/// sks.smart_sub_assign(&mut ctxt_1, &mut ctxt_2);
///
/// // Decrypt:
/// let res = cks.decrypt(&ctxt_1);
/// let res: u64 = cks.decrypt(&ctxt_1);
/// assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
/// ```
pub fn smart_sub_assign<PBSOrder: PBSOrderMarker>(

View File

@@ -31,7 +31,7 @@ impl ServerKey {
/// let ct_res = sks.smart_add_parallelized(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 + msg2);
/// ```
pub fn smart_add_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -53,7 +53,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitand_parallelized(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 & msg2);
/// ```
pub fn smart_bitand_parallelized<PBSOrder: PBSOrderMarker>(
@@ -133,7 +133,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 | msg2);
/// ```
pub fn smart_bitor_parallelized<PBSOrder: PBSOrderMarker>(
@@ -213,7 +213,7 @@ impl ServerKey {
/// let ct_res = sks.smart_bitxor_parallelized(&mut ct1, &mut ct2);
///
/// // Decrypt:
/// let dec_result = cks.decrypt(&ct_res);
/// let dec_result: u64 = cks.decrypt(&ct_res);
/// assert_eq!(dec_result, msg1 ^ msg2);
/// ```
pub fn smart_bitxor_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -30,7 +30,7 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg = 7;
/// let msg = 7u64;
///
/// let ct1 = cks.encrypt(msg);
/// let ct2 = cks.encrypt(msg);
@@ -40,7 +40,7 @@ impl ServerKey {
/// sks.propagate_parallelized(&mut ct_res, 0);
///
/// // Decrypt one block:
/// let res = cks.decrypt_one_block(&ct_res.blocks()[1]);
/// let res: u64 = cks.decrypt_one_block(&ct_res.blocks()[1]);
/// assert_eq!(3, res);
/// ```
pub fn propagate_parallelized<PBSOrder: PBSOrderMarker>(
@@ -73,7 +73,7 @@ impl ServerKey {
/// let num_blocks = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
///
/// let msg = 10;
/// let msg = 10u64;
///
/// let mut ct1 = cks.encrypt(msg);
/// let mut ct2 = cks.encrypt(msg);
@@ -83,7 +83,7 @@ impl ServerKey {
/// sks.full_propagate_parallelized(&mut ct_res);
///
/// // Decrypt:
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + msg, res);
/// ```
pub fn full_propagate_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -39,7 +39,7 @@ impl ServerKey {
/// sks.unchecked_block_mul_assign_parallelized(&mut ct_left, &ct_right, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_left);
/// let res: u64 = cks.decrypt(&ct_left);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_block_mul_assign_parallelized<PBSOrder: PBSOrderMarker>(
@@ -84,7 +84,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_block_mul_parallelized(&ct_left, &ct_right, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_block_mul_parallelized<PBSOrder: PBSOrderMarker>(
@@ -133,7 +133,7 @@ impl ServerKey {
/// let ct_res = sks.smart_block_mul_parallelized(&mut ctxt_1, &ctxt_2, 0);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn smart_block_mul_parallelized<PBSOrder: PBSOrderMarker>(
@@ -222,7 +222,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_mul_parallelized(&mut ctxt_1, &ctxt_2);
///
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn unchecked_mul_assign_parallelized<PBSOrder: PBSOrderMarker>(
@@ -294,7 +294,7 @@ impl ServerKey {
/// // Compute homomorphically a multiplication
/// let ct_res = sks.smart_mul_parallelized(&mut ctxt_1, &mut ctxt_2);
/// // Decrypt
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!((clear_1 * clear_2) % 256, res);
/// ```
pub fn smart_mul_assign_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -17,7 +17,7 @@ impl ServerKey {
/// let size = 4;
/// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);
///
/// let msg = 1;
/// let msg = 1u64;
///
/// // Encrypt two messages:
/// let mut ctxt = cks.encrypt(msg);
@@ -26,7 +26,7 @@ impl ServerKey {
/// let ct_res = sks.smart_neg_parallelized(&mut ctxt);
///
/// // Decrypt
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(255, dec);
/// ```
pub fn smart_neg_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -26,7 +26,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_add_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg + scalar, dec);
/// ```
pub fn smart_scalar_add_parallelized<PBSOrder: PBSOrderMarker>(
@@ -63,7 +63,7 @@ impl ServerKey {
/// sks.smart_scalar_add_assign_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg + scalar, dec);
/// ```
pub fn smart_scalar_add_assign_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -33,7 +33,7 @@ impl ServerKey {
/// // Compute homomorphically a scalar multiplication:
/// let ct_res = sks.unchecked_small_scalar_mul_parallelized(&ct, scalar);
///
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(scalar * msg, clear);
/// ```
pub fn unchecked_small_scalar_mul_parallelized<PBSOrder: PBSOrderMarker>(
@@ -82,7 +82,7 @@ impl ServerKey {
/// match ct_res {
/// Err(x) => panic!("{:?}", x),
/// Ok(y) => {
/// let clear = cks.decrypt(&y);
/// let clear: u64 = cks.decrypt(&y);
/// assert_eq!(msg * scalar, clear);
/// }
/// }
@@ -124,7 +124,7 @@ impl ServerKey {
/// // Compute homomorphically a scalar multiplication:
/// sks.checked_small_scalar_mul_assign_parallelized(&mut ct, scalar);
///
/// let clear_res = cks.decrypt(&ct);
/// let clear_res: u64 = cks.decrypt(&ct);
/// assert_eq!(clear_res, msg * scalar);
/// ```
pub fn checked_small_scalar_mul_assign_parallelized<PBSOrder: PBSOrderMarker>(
@@ -169,7 +169,7 @@ impl ServerKey {
/// let ct_res = sks.smart_small_scalar_mul_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_small_scalar_mul_parallelized<PBSOrder: PBSOrderMarker>(
@@ -211,7 +211,7 @@ impl ServerKey {
/// sks.smart_small_scalar_mul_assign_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct);
/// let clear: u64 = cks.decrypt(&ct);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_small_scalar_mul_assign_parallelized<PBSOrder: PBSOrderMarker>(
@@ -248,7 +248,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_mul_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let clear = cks.decrypt(&ct_res);
/// let clear: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg * scalar % modulus, clear);
/// ```
pub fn smart_scalar_mul_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -24,7 +24,7 @@ impl ServerKey {
/// let ct_res = sks.smart_scalar_sub_parallelized(&mut ct, scalar);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg - scalar, dec);
/// ```
pub fn smart_scalar_sub_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -26,7 +26,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_right_shift_parallelized(&ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg >> shift, dec);
/// ```
pub fn unchecked_scalar_right_shift_parallelized<PBSOrder: PBSOrderMarker>(
@@ -62,7 +62,7 @@ impl ServerKey {
/// sks.unchecked_scalar_right_shift_assign_parallelized(&mut ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg >> shift, dec);
/// ```
pub fn unchecked_scalar_right_shift_assign_parallelized<PBSOrder: PBSOrderMarker>(
@@ -134,7 +134,7 @@ impl ServerKey {
/// let ct_res = sks.unchecked_scalar_left_shift_parallelized(&ct1, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct_res);
/// let dec: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg << shift, dec);
/// ```
pub fn unchecked_scalar_left_shift_parallelized<PBSOrder: PBSOrderMarker>(
@@ -170,7 +170,7 @@ impl ServerKey {
/// sks.unchecked_scalar_left_shift_assign_parallelized(&mut ct, shift);
///
/// // Decrypt:
/// let dec = cks.decrypt(&ct);
/// let dec: u64 = cks.decrypt(&ct);
/// assert_eq!(msg << shift, dec);
/// ```
pub fn unchecked_scalar_left_shift_assign_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -26,7 +26,7 @@ impl ServerKey {
/// let ct_res = sks.smart_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
///
/// // Decrypt:
/// let res = cks.decrypt(&ct_res);
/// let res: u64 = cks.decrypt(&ct_res);
/// assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
/// ```
pub fn smart_sub_parallelized<PBSOrder: PBSOrderMarker>(
@@ -76,7 +76,7 @@ impl ServerKey {
/// sks.smart_sub_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
///
/// // Decrypt:
/// let res = cks.decrypt(&ctxt_1);
/// let res: u64 = cks.decrypt(&ctxt_1);
/// assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
/// ```
pub fn smart_sub_assign_parallelized<PBSOrder: PBSOrderMarker>(

View File

@@ -252,6 +252,12 @@ impl NamedParam for Parameters {
PARAM_MESSAGE_7_CARRY_0,
PARAM_MESSAGE_7_CARRY_1,
PARAM_MESSAGE_8_CARRY_0,
// Small
PARAM_SMALL_MESSAGE_1_CARRY_1,
PARAM_SMALL_MESSAGE_2_CARRY_2,
PARAM_SMALL_MESSAGE_3_CARRY_3,
PARAM_SMALL_MESSAGE_4_CARRY_4,
// Wops
WOPBS_PARAM_MESSAGE_1_NORM2_2,
WOPBS_PARAM_MESSAGE_1_NORM2_4,
WOPBS_PARAM_MESSAGE_1_NORM2_6,

View File

@@ -122,7 +122,7 @@ impl ServerKey {
/// // Generate the client key and the server key:
/// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
///
/// let msg = 2;
/// let msg = 2u64;
///
/// // Encrypt two messages:
/// let ct_left = cks.encrypt(msg);

View File

@@ -113,6 +113,13 @@ impl ConfigBuilder {
self
}
#[cfg(feature = "integer")]
pub fn enable_default_uint8_small(mut self) -> Self {
let params = crate::typed_api::integers::FheUint8Parameters::small();
self.config.integer_config.uint8_params = Some(params);
self
}
#[cfg(feature = "integer")]
pub fn disable_uint8(mut self) -> Self {
self.config.integer_config.uint8_params = None;
@@ -125,6 +132,13 @@ impl ConfigBuilder {
self
}
#[cfg(feature = "integer")]
pub fn enable_default_uint12_small(mut self) -> Self {
let params = crate::typed_api::integers::FheUint12Parameters::small();
self.config.integer_config.uint12_params = Some(params);
self
}
#[cfg(feature = "integer")]
pub fn disable_uint12(mut self) -> Self {
self.config.integer_config.uint12_params = None;
@@ -137,6 +151,13 @@ impl ConfigBuilder {
self
}
#[cfg(feature = "integer")]
pub fn enable_default_uint16_small(mut self) -> Self {
let params = crate::typed_api::integers::FheUint16Parameters::small();
self.config.integer_config.uint16_params = Some(params);
self
}
#[cfg(feature = "integer")]
pub fn disable_uint16(mut self) -> Self {
self.config.integer_config.uint16_params = None;
@@ -149,6 +170,13 @@ impl ConfigBuilder {
self
}
#[cfg(feature = "integer")]
pub fn enable_default_uint256_small(mut self) -> Self {
let params = crate::typed_api::integers::FheUint256Parameters::small();
self.config.integer_config.uint256_params = Some(params);
self
}
#[cfg(feature = "integer")]
pub fn disable_uint256(mut self) -> Self {
self.config.integer_config.uint256_params = None;

View File

@@ -1,55 +1,111 @@
use serde::{Deserialize, Serialize};
use crate::integer::{CrtCiphertext, CrtClientKey, RadixCiphertextBig, RadixClientKey, U256};
use crate::typed_api::integers::parameters::IntegerParameter;
use crate::integer::{CrtCiphertext, CrtClientKey, U256};
use crate::typed_api::integers::parameters::{IntegerParameter, RadixParameters};
use crate::typed_api::internal_traits::{DecryptionKey, EncryptionKey, FromParameters};
impl EncryptionKey<u64> for RadixClientKey {
type Ciphertext = RadixCiphertextBig;
use super::server_key::RadixCiphertextDyn;
fn encrypt(&self, value: u64) -> Self::Ciphertext {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct RadixClientKey {
pub(in crate::typed_api::integers) inner: crate::integer::RadixClientKey,
// To know if we have to encrypt into a big or small ciphertext
pub(in crate::typed_api::integers) pbs_order: crate::shortint::PBSOrder,
}
// This is needed by the impl EvaluationKey
impl AsRef<crate::integer::ClientKey> for RadixClientKey {
fn as_ref(&self) -> &crate::integer::ClientKey {
self.inner.as_ref()
}
}
impl<P> FromParameters<P> for RadixClientKey
where
P: Into<RadixParameters>,
{
fn from_parameters(parameters: P) -> Self {
let params = parameters.into();
#[cfg(feature = "internal-keycache")]
{
use crate::integer::keycache::KEY_CACHE;
let key = KEY_CACHE.get_from_params(params.block_parameters).0;
let inner = crate::integer::RadixClientKey::from((key, params.num_block));
Self {
inner,
pbs_order: params.pbs_order,
}
}
#[cfg(not(feature = "internal-keycache"))]
{
let inner =
crate::integer::RadixClientKey::new(params.block_parameters, params.num_block);
Self {
inner,
pbs_order: params.pbs_order,
}
}
}
}
impl EncryptionKey<u64, RadixCiphertextDyn> for RadixClientKey {
fn encrypt(&self, value: u64) -> RadixCiphertextDyn {
match self.pbs_order {
crate::shortint::PBSOrder::KeyswitchBootstrap => {
RadixCiphertextDyn::Big(self.inner.encrypt(value))
}
crate::shortint::PBSOrder::BootstrapKeyswitch => RadixCiphertextDyn::Small(
self.inner
.as_ref()
.encrypt_radix_small(value, self.inner.num_blocks()),
),
}
}
}
impl EncryptionKey<U256, RadixCiphertextDyn> for RadixClientKey {
fn encrypt(&self, value: U256) -> RadixCiphertextDyn {
match self.pbs_order {
crate::shortint::PBSOrder::KeyswitchBootstrap => RadixCiphertextDyn::Big(
self.inner
.as_ref()
.encrypt_radix(value, self.inner.num_blocks()),
),
crate::shortint::PBSOrder::BootstrapKeyswitch => RadixCiphertextDyn::Small(
self.inner
.as_ref()
.encrypt_radix_small(value, self.inner.num_blocks()),
),
}
}
}
impl DecryptionKey<RadixCiphertextDyn, u64> for RadixClientKey {
fn decrypt(&self, ciphertext: &RadixCiphertextDyn) -> u64 {
match ciphertext {
RadixCiphertextDyn::Big(ct) => self.inner.decrypt(ct),
RadixCiphertextDyn::Small(ct) => self.inner.decrypt(ct),
}
}
}
impl DecryptionKey<RadixCiphertextDyn, U256> for RadixClientKey {
fn decrypt(&self, ciphertext: &RadixCiphertextDyn) -> U256 {
match ciphertext {
RadixCiphertextDyn::Big(ct) => self.inner.decrypt(ct),
RadixCiphertextDyn::Small(ct) => self.inner.decrypt(ct),
}
}
}
impl EncryptionKey<u64, CrtCiphertext> for CrtClientKey {
fn encrypt(&self, value: u64) -> CrtCiphertext {
self.encrypt(value)
}
}
impl EncryptionKey<U256> for RadixClientKey {
type Ciphertext = RadixCiphertextBig;
fn encrypt(&self, value: U256) -> Self::Ciphertext {
self.as_ref().encrypt_radix(value, self.num_blocks())
}
}
impl DecryptionKey<u64> for RadixClientKey {
type Ciphertext = RadixCiphertextBig;
fn decrypt(&self, ciphertext: &Self::Ciphertext) -> u64 {
self.decrypt(ciphertext)
}
}
impl DecryptionKey<U256> for RadixClientKey {
type Ciphertext = RadixCiphertextBig;
fn decrypt(&self, ciphertext: &Self::Ciphertext) -> U256 {
let mut r = U256::default();
self.as_ref().decrypt_radix_into(ciphertext, &mut r);
r
}
}
impl EncryptionKey<u64> for CrtClientKey {
type Ciphertext = CrtCiphertext;
fn encrypt(&self, value: u64) -> Self::Ciphertext {
self.encrypt(value)
}
}
impl DecryptionKey<u64> for CrtClientKey {
type Ciphertext = CrtCiphertext;
fn decrypt(&self, ciphertext: &Self::Ciphertext) -> u64 {
impl DecryptionKey<CrtCiphertext, u64> for CrtClientKey {
fn decrypt(&self, ciphertext: &CrtCiphertext) -> u64 {
self.decrypt(ciphertext)
}
}

View File

@@ -1,5 +1,8 @@
pub(crate) use keys::{IntegerClientKey, IntegerConfig, IntegerPublicKey, IntegerServerKey};
pub use parameters::{CrtParameters, RadixParameters};
pub(in crate::typed_api) use types::static_::{
FheUint12Parameters, FheUint16Parameters, FheUint256Parameters, FheUint8Parameters,
};
pub use types::{FheUint10, FheUint12, FheUint14, FheUint16, FheUint256, FheUint8, GenericInteger};
mod client_key;

View File

@@ -1,4 +1,4 @@
use crate::integer::{CrtCiphertext, CrtClientKey, RadixCiphertextBig, RadixClientKey};
use crate::integer::CrtClientKey;
use crate::typed_api::internal_traits::{FromParameters, ParameterType};
use serde::{Deserialize, Serialize};
@@ -13,6 +13,7 @@ use serde::{Deserialize, Serialize};
pub struct RadixParameters {
pub block_parameters: crate::shortint::Parameters,
pub num_block: usize,
pub pbs_order: crate::shortint::PBSOrder,
pub wopbs_block_parameters: crate::shortint::Parameters,
}
@@ -38,25 +39,6 @@ pub trait EvaluationIntegerKey<ClientKey> {
) -> crate::integer::wopbs::WopbsKey;
}
impl<P> FromParameters<P> for crate::integer::RadixClientKey
where
P: Into<RadixParameters>,
{
fn from_parameters(parameters: P) -> Self {
let params = parameters.into();
#[cfg(feature = "internal-keycache")]
{
use crate::integer::keycache::KEY_CACHE;
let key = KEY_CACHE.get_from_params(params.block_parameters).0;
crate::integer::RadixClientKey::from((key, params.num_block))
}
#[cfg(not(feature = "internal-keycache"))]
{
crate::integer::RadixClientKey::new(params.block_parameters, params.num_block)
}
}
}
impl<P> FromParameters<P> for crate::integer::CrtClientKey
where
P: Into<CrtParameters>,
@@ -105,18 +87,14 @@ pub trait StaticRadixParameter:
StaticIntegerParameter<Representation = RadixRepresentation>
where
Self: IntegerParameter<
InnerClientKey = RadixClientKey,
InnerClientKey = crate::typed_api::integers::client_key::RadixClientKey,
InnerServerKey = crate::integer::ServerKey,
InnerCiphertext = RadixCiphertextBig,
>,
{
}
pub trait StaticCrtParameter: StaticIntegerParameter<Representation = CrtRepresentation>
where
Self: IntegerParameter<
InnerClientKey = CrtClientKey,
InnerServerKey = crate::integer::ServerKey,
InnerCiphertext = CrtCiphertext,
>,
Self:
IntegerParameter<InnerClientKey = CrtClientKey, InnerServerKey = crate::integer::ServerKey>,
{
}

View File

@@ -1,14 +1,22 @@
use crate::typed_api::integers::client_key::GenericIntegerClientKey;
use crate::integer::{CrtCiphertext, CrtClientKey, RadixCiphertextBig, RadixClientKey, U256};
use crate::integer::{CrtCiphertext, CrtClientKey, U256};
use crate::typed_api::integers::client_key::RadixClientKey;
use crate::typed_api::internal_traits::{EncryptionKey, ParameterType};
use serde::{Deserialize, Serialize};
use super::parameters::IntegerParameter;
use super::server_key::RadixCiphertextDyn;
#[derive(Clone, Debug, Serialize, Deserialize)]
enum PublicKeyDyn {
Big(crate::integer::PublicKeyBig),
Small(crate::integer::PublicKeySmall),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RadixPublicKey {
key: crate::integer::PublicKeyBig,
key: PublicKeyDyn,
num_blocks: usize,
}
@@ -28,26 +36,45 @@ impl IntegerPublicKey for RadixPublicKey {
type ClientKey = RadixClientKey;
fn new(client_key: &Self::ClientKey) -> Self {
let key = match client_key.pbs_order {
crate::shortint::PBSOrder::KeyswitchBootstrap => {
PublicKeyDyn::Big(crate::integer::PublicKeyBig::new(client_key.inner.as_ref()))
}
crate::shortint::PBSOrder::BootstrapKeyswitch => PublicKeyDyn::Small(
crate::integer::PublicKeySmall::new(client_key.inner.as_ref()),
),
};
Self {
key: crate::integer::PublicKeyBig::new(client_key.as_ref()),
num_blocks: client_key.num_blocks(),
key,
num_blocks: client_key.inner.num_blocks(),
}
}
}
impl EncryptionKey<u64> for RadixPublicKey {
type Ciphertext = RadixCiphertextBig;
fn encrypt(&self, value: u64) -> Self::Ciphertext {
self.key.encrypt_radix(value, self.num_blocks)
impl EncryptionKey<u64, RadixCiphertextDyn> for RadixPublicKey {
fn encrypt(&self, value: u64) -> RadixCiphertextDyn {
match &self.key {
PublicKeyDyn::Big(key) => {
RadixCiphertextDyn::Big(key.encrypt_radix(value, self.num_blocks))
}
PublicKeyDyn::Small(key) => {
RadixCiphertextDyn::Small(key.encrypt_radix(value, self.num_blocks))
}
}
}
}
impl EncryptionKey<U256> for RadixPublicKey {
type Ciphertext = RadixCiphertextBig;
fn encrypt(&self, value: U256) -> Self::Ciphertext {
self.key.encrypt_radix(value, self.num_blocks)
impl EncryptionKey<U256, RadixCiphertextDyn> for RadixPublicKey {
fn encrypt(&self, value: U256) -> RadixCiphertextDyn {
match &self.key {
PublicKeyDyn::Big(key) => {
RadixCiphertextDyn::Big(key.encrypt_radix(value, self.num_blocks))
}
PublicKeyDyn::Small(key) => {
RadixCiphertextDyn::Small(key.encrypt_radix(value, self.num_blocks))
}
}
}
}
@@ -62,10 +89,8 @@ impl IntegerPublicKey for CrtPublicKey {
}
}
impl EncryptionKey<u64> for CrtPublicKey {
type Ciphertext = CrtCiphertext;
fn encrypt(&self, value: u64) -> Self::Ciphertext {
impl EncryptionKey<u64, CrtCiphertext> for CrtPublicKey {
fn encrypt(&self, value: u64) -> CrtCiphertext {
self.key.encrypt_crt(value, self.moduli.clone())
}
}

View File

@@ -34,6 +34,146 @@ where
}
}
pub(crate) fn wopbs_radix<O>(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
ct_in: &crate::integer::ciphertext::RadixCiphertext<O>,
func: impl Fn(u64) -> u64,
) -> crate::integer::ciphertext::RadixCiphertext<O>
where
O: crate::shortint::PBSOrderMarker,
crate::integer::ciphertext::RadixCiphertext<O>: crate::integer::IntegerCiphertext,
{
let switched_ct = wopbs_key.keyswitch_to_wopbs_params(server_key, ct_in);
let luts = wopbs_key.generate_lut_radix(&switched_ct, func);
let res = wopbs_key.wopbs(&switched_ct, luts.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn bivariate_wopbs_radix<O>(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
lhs: &crate::integer::ciphertext::RadixCiphertext<O>,
rhs: &crate::integer::ciphertext::RadixCiphertext<O>,
func: impl Fn(u64, u64) -> u64,
) -> crate::integer::ciphertext::RadixCiphertext<O>
where
O: crate::shortint::PBSOrderMarker,
crate::integer::ciphertext::RadixCiphertext<O>: crate::integer::IntegerCiphertext,
{
let switched_lhs = wopbs_key.keyswitch_to_wopbs_params(server_key, lhs);
let switched_rhs = wopbs_key.keyswitch_to_wopbs_params(server_key, rhs);
let lut = wopbs_key.generate_lut_bivariate_radix(&switched_lhs, &switched_rhs, func);
let res = wopbs_key.bivariate_wopbs_with_degree(&switched_lhs, &switched_rhs, lut.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn wopbs_crt(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
ct_in: &crate::integer::CrtCiphertext,
func: impl Fn(u64) -> u64,
) -> crate::integer::CrtCiphertext {
let switched_ct = wopbs_key.keyswitch_to_wopbs_params(server_key, ct_in);
let luts = wopbs_key.generate_lut_crt(&switched_ct, func);
let res = wopbs_key.wopbs(&switched_ct, luts.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn bivariate_wopbs_crt(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
lhs: &crate::integer::CrtCiphertext,
rhs: &crate::integer::CrtCiphertext,
func: impl Fn(u64, u64) -> u64,
) -> crate::integer::CrtCiphertext {
let switched_lhs = wopbs_key.keyswitch_to_wopbs_params(server_key, lhs);
let switched_rhs = wopbs_key.keyswitch_to_wopbs_params(server_key, rhs);
let lut = wopbs_key.generate_lut_bivariate_crt(&switched_lhs, &switched_rhs, func);
let res = wopbs_key.bivariate_wopbs_native_crt(&switched_lhs, &switched_rhs, lut.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub trait WopbsEvaluationKey<ServerKey, Ciphertext> {
fn apply_wopbs(&self, sks: &ServerKey, ct: &Ciphertext, f: impl Fn(u64) -> u64) -> Ciphertext;
fn apply_bivariate_wopbs(
&self,
sks: &ServerKey,
lhs: &Ciphertext,
rhs: &Ciphertext,
f: impl Fn(u64, u64) -> u64,
) -> Ciphertext;
}
impl
WopbsEvaluationKey<
crate::integer::ServerKey,
crate::typed_api::integers::server_key::RadixCiphertextDyn,
> for WopbsKey
{
fn apply_wopbs(
&self,
sks: &crate::integer::ServerKey,
ct: &crate::typed_api::integers::server_key::RadixCiphertextDyn,
f: impl Fn(u64) -> u64,
) -> crate::typed_api::integers::server_key::RadixCiphertextDyn {
match ct {
RadixCiphertextDyn::Big(ct) => {
let res = wopbs_radix(self, sks, ct, f);
RadixCiphertextDyn::Big(res)
}
RadixCiphertextDyn::Small(ct) => {
let res = wopbs_radix(self, sks, ct, f);
RadixCiphertextDyn::Small(res)
}
}
}
fn apply_bivariate_wopbs(
&self,
sks: &crate::integer::ServerKey,
lhs: &crate::typed_api::integers::server_key::RadixCiphertextDyn,
rhs: &crate::typed_api::integers::server_key::RadixCiphertextDyn,
f: impl Fn(u64, u64) -> u64,
) -> crate::typed_api::integers::server_key::RadixCiphertextDyn {
match (lhs, rhs) {
(RadixCiphertextDyn::Big(lhs), RadixCiphertextDyn::Big(rhs)) => {
let res = bivariate_wopbs_radix(self, sks, lhs, rhs, f);
RadixCiphertextDyn::Big(res)
}
(RadixCiphertextDyn::Small(lhs), RadixCiphertextDyn::Small(rhs)) => {
let res = bivariate_wopbs_radix(self, sks, lhs, rhs, f);
RadixCiphertextDyn::Small(res)
}
(_, _) => {
unreachable!("internal error: cannot mix big and small ciphertext")
}
}
}
}
impl WopbsEvaluationKey<crate::integer::ServerKey, crate::integer::CrtCiphertext> for WopbsKey {
fn apply_wopbs(
&self,
sks: &crate::integer::ServerKey,
ct: &crate::integer::CrtCiphertext,
f: impl Fn(u64) -> u64,
) -> crate::integer::CrtCiphertext {
wopbs_crt(self, sks, ct, f)
}
fn apply_bivariate_wopbs(
&self,
sks: &crate::integer::ServerKey,
lhs: &crate::integer::CrtCiphertext,
rhs: &crate::integer::CrtCiphertext,
f: impl Fn(u64, u64) -> u64,
) -> crate::integer::CrtCiphertext {
bivariate_wopbs_crt(self, sks, lhs, rhs, f)
}
}
pub(super) trait SmartNeg<Ciphertext> {
type Output;
fn smart_neg(&self, lhs: Ciphertext) -> Self::Output;
@@ -72,115 +212,141 @@ define_smart_server_key_op!(
Add, Sub, Mul, BitAnd, BitOr, BitXor, Shl, Shr, Eq, Ge, Gt, Le, Lt, Max, Min
);
macro_rules! impl_smart_op_for_tfhe_integer_server_key {
($smart_trait:ident($smart_trait_fn:ident) => ($ciphertext:ty, $method:ident)) => {
impl $smart_trait<&mut $ciphertext, &mut $ciphertext> for crate::integer::ServerKey {
type Output = $ciphertext;
#[derive(Clone, serde::Deserialize, serde::Serialize)]
pub enum RadixCiphertextDyn {
Big(crate::integer::RadixCiphertextBig),
Small(crate::integer::RadixCiphertextSmall),
}
impl SmartNeg<&mut RadixCiphertextDyn> for crate::integer::ServerKey {
type Output = RadixCiphertextDyn;
fn smart_neg(&self, lhs: &mut RadixCiphertextDyn) -> Self::Output {
match lhs {
RadixCiphertextDyn::Big(lhs) => {
RadixCiphertextDyn::Big(self.smart_neg_parallelized(lhs))
}
RadixCiphertextDyn::Small(lhs) => {
RadixCiphertextDyn::Small(self.smart_neg_parallelized(lhs))
}
}
}
}
macro_rules! impl_smart_op_for_tfhe_integer_server_key_dyn {
($smart_trait:ident($smart_trait_fn:ident) => $method:ident) => {
impl $smart_trait<&mut RadixCiphertextDyn, &mut RadixCiphertextDyn>
for crate::integer::ServerKey
{
type Output = RadixCiphertextDyn;
fn $smart_trait_fn(
&self,
lhs: &mut $ciphertext,
rhs: &mut $ciphertext,
lhs_enum: &mut RadixCiphertextDyn,
rhs_enum: &mut RadixCiphertextDyn,
) -> Self::Output {
self.$method(lhs, rhs)
match (lhs_enum, rhs_enum) {
(RadixCiphertextDyn::Big(lhs), RadixCiphertextDyn::Big(rhs)) => {
RadixCiphertextDyn::Big(self.$method(lhs, rhs))
}
(RadixCiphertextDyn::Small(lhs), RadixCiphertextDyn::Small(rhs)) => {
RadixCiphertextDyn::Small(self.$method(lhs, rhs))
}
(_, _) => unreachable!("internal error: mismatched big and small integer"),
}
}
}
};
}
macro_rules! impl_smart_assign_op_for_tfhe_integer_server_key {
($smart_trait:ident($smart_trait_fn:ident) => ($ciphertext:ty, $method:ident)) => {
impl $smart_trait<$ciphertext, &mut $ciphertext> for crate::integer::ServerKey {
fn $smart_trait_fn(&self, lhs: &mut $ciphertext, rhs: &mut $ciphertext) {
self.$method(lhs, rhs);
macro_rules! impl_smart_assign_op_for_tfhe_integer_server_key_dyn {
($smart_trait:ident($smart_trait_fn:ident) => $method_assign:ident) => {
impl $smart_trait<RadixCiphertextDyn, &mut RadixCiphertextDyn>
for crate::integer::ServerKey
{
fn $smart_trait_fn(
&self,
lhs_enum: &mut RadixCiphertextDyn,
rhs_enum: &mut RadixCiphertextDyn,
) {
match (lhs_enum, rhs_enum) {
(RadixCiphertextDyn::Big(lhs), RadixCiphertextDyn::Big(rhs)) => {
self.$method_assign(lhs, rhs)
}
(RadixCiphertextDyn::Small(lhs), RadixCiphertextDyn::Small(rhs)) => {
self.$method_assign(lhs, rhs)
}
(_, _) => unreachable!("internal error: mismatched big and small integer"),
}
}
}
};
}
macro_rules! impl_smart_scalar_op_for_tfhe_integer_server_key {
($smart_trait:ident($smart_trait_fn:ident) => ($ciphertext:ty, $method:ident)) => {
impl $smart_trait<&mut $ciphertext, u64> for crate::integer::ServerKey {
type Output = $ciphertext;
macro_rules! impl_smart_scalar_op_for_tfhe_integer_server_key_dyn {
($smart_trait:ident($smart_trait_fn:ident) => $method:ident) => {
impl $smart_trait<&mut RadixCiphertextDyn, u64> for crate::integer::ServerKey {
type Output = RadixCiphertextDyn;
fn $smart_trait_fn(&self, lhs: &mut $ciphertext, rhs: u64) -> Self::Output {
self.$method(lhs, rhs.try_into().unwrap())
fn $smart_trait_fn(&self, lhs: &mut RadixCiphertextDyn, rhs: u64) -> Self::Output {
match lhs {
RadixCiphertextDyn::Big(lhs) => {
RadixCiphertextDyn::Big(self.$method(lhs, rhs.try_into().unwrap()))
}
RadixCiphertextDyn::Small(lhs) => {
RadixCiphertextDyn::Small(self.$method(lhs, rhs.try_into().unwrap()))
}
}
}
}
};
}
macro_rules! impl_smart_scalar_assign_op_for_tfhe_integer_server_key {
($smart_trait:ident($smart_trait_fn:ident) => ($ciphertext:ty, $method:ident)) => {
impl $smart_trait<$ciphertext, u64> for crate::integer::ServerKey {
fn $smart_trait_fn(&self, lhs: &mut $ciphertext, rhs: u64) {
self.$method(lhs, rhs.try_into().unwrap());
macro_rules! impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn {
($smart_trait:ident($smart_trait_fn:ident) => $method_assign:ident) => {
impl $smart_trait<RadixCiphertextDyn, u64> for crate::integer::ServerKey {
fn $smart_trait_fn(&self, lhs: &mut RadixCiphertextDyn, rhs: u64) {
match lhs {
RadixCiphertextDyn::Big(lhs) => {
self.$method_assign(lhs, rhs.try_into().unwrap())
}
RadixCiphertextDyn::Small(lhs) => {
self.$method_assign(lhs, rhs.try_into().unwrap())
}
}
}
}
};
}
impl SmartNeg<&mut crate::integer::RadixCiphertextBig> for crate::integer::ServerKey {
type Output = crate::integer::RadixCiphertextBig;
fn smart_neg(&self, lhs: &mut crate::integer::RadixCiphertextBig) -> Self::Output {
self.smart_neg_parallelized(lhs)
}
}
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartAdd(smart_add) => smart_add_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartSub(smart_sub) => smart_sub_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartMul(smart_mul) => smart_mul_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartBitAnd(smart_bitand) => smart_bitand_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartBitOr(smart_bitor) => smart_bitor_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartBitXor(smart_bitxor) => smart_bitxor_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartEq(smart_eq) => smart_eq_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartGe(smart_ge) => smart_ge_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartGt(smart_gt) => smart_gt_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartLe(smart_le) => smart_le_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartLt(smart_lt) => smart_lt_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartMax(smart_max) => smart_max_parallelized);
impl_smart_op_for_tfhe_integer_server_key_dyn!(SmartMin(smart_min) => smart_min_parallelized);
impl_smart_op_for_tfhe_integer_server_key!(SmartAdd(smart_add) => (crate::integer::RadixCiphertextBig, smart_add_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartSub(smart_sub) => (crate::integer::RadixCiphertextBig, smart_sub_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartMul(smart_mul) => (crate::integer::RadixCiphertextBig, smart_mul_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartBitAnd(smart_bitand) => (crate::integer::RadixCiphertextBig, smart_bitand_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartBitOr(smart_bitor) => (crate::integer::RadixCiphertextBig, smart_bitor_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartBitXor(smart_bitxor) => (crate::integer::RadixCiphertextBig, smart_bitxor_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartEq(smart_eq) => (crate::integer::RadixCiphertextBig, smart_eq_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartGe(smart_ge) => (crate::integer::RadixCiphertextBig, smart_ge_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartGt(smart_gt) => (crate::integer::RadixCiphertextBig, smart_gt_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartLe(smart_le) => (crate::integer::RadixCiphertextBig, smart_le_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartLt(smart_lt) => (crate::integer::RadixCiphertextBig, smart_lt_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartMax(smart_max) => (crate::integer::RadixCiphertextBig, smart_max_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartMin(smart_min) => (crate::integer::RadixCiphertextBig, smart_min_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartAddAssign(smart_add_assign) => smart_add_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartSubAssign(smart_sub_assign) => smart_sub_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartMulAssign(smart_mul_assign) => smart_mul_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartBitAndAssign(smart_bitand_assign) => smart_bitand_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartBitOrAssign(smart_bitor_assign) => smart_bitor_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key_dyn!(SmartBitXorAssign(smart_bitxor_assign) => smart_bitxor_assign_parallelized);
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartAddAssign(smart_add_assign) => (crate::integer::RadixCiphertextBig, smart_add_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartSubAssign(smart_sub_assign) => (crate::integer::RadixCiphertextBig, smart_sub_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartMulAssign(smart_mul_assign) => (crate::integer::RadixCiphertextBig, smart_mul_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartBitAndAssign(smart_bitand_assign) => (crate::integer::RadixCiphertextBig, smart_bitand_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartBitOrAssign(smart_bitor_assign) => (crate::integer::RadixCiphertextBig, smart_bitor_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartBitXorAssign(smart_bitxor_assign) => (crate::integer::RadixCiphertextBig, smart_bitxor_assign_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key_dyn!(SmartAdd(smart_add) => smart_scalar_add_parallelized);
impl_smart_scalar_op_for_tfhe_integer_server_key_dyn!(SmartSub(smart_sub) => smart_scalar_sub_parallelized);
impl_smart_scalar_op_for_tfhe_integer_server_key_dyn!(SmartMul(smart_mul) => smart_scalar_mul_parallelized);
impl_smart_scalar_op_for_tfhe_integer_server_key_dyn!(SmartShl(smart_shl) => unchecked_scalar_left_shift_parallelized);
impl_smart_scalar_op_for_tfhe_integer_server_key_dyn!(SmartShr(smart_shr) => unchecked_scalar_right_shift_parallelized);
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartAdd(smart_add) => (crate::integer::RadixCiphertextBig, smart_scalar_add_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartSub(smart_sub) => (crate::integer::RadixCiphertextBig, smart_scalar_sub_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartMul(smart_mul) => (crate::integer::RadixCiphertextBig, smart_scalar_mul_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartShl(smart_shl) => (crate::integer::RadixCiphertextBig, unchecked_scalar_left_shift_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartShr(smart_shr) => (crate::integer::RadixCiphertextBig, unchecked_scalar_right_shift_parallelized));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartAddAssign(smart_add_assign) => (crate::integer::RadixCiphertextBig, smart_scalar_add_assign_parallelized));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartSubAssign(smart_sub_assign) => (crate::integer::RadixCiphertextBig, smart_scalar_sub_assign_parallelized));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartMulAssign(smart_mul_assign) => (crate::integer::RadixCiphertextBig, smart_scalar_mul_assign_parallelized));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartShlAssign(smart_shl_assign) => (crate::integer::RadixCiphertextBig, unchecked_scalar_left_shift_assign_parallelized));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartShrAssign(smart_shr_assign) => (crate::integer::RadixCiphertextBig, unchecked_scalar_right_shift_assign_parallelized));
// Crt
impl_smart_op_for_tfhe_integer_server_key!(SmartAdd(smart_add) => (crate::integer::CrtCiphertext, smart_crt_add_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartSub(smart_sub) => (crate::integer::CrtCiphertext, smart_crt_sub_parallelized));
impl_smart_op_for_tfhe_integer_server_key!(SmartMul(smart_mul) => (crate::integer::CrtCiphertext, smart_crt_mul_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartAddAssign(smart_add_assign) => (crate::integer::CrtCiphertext, smart_crt_add_assign_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartSubAssign(smart_sub_assign) => (crate::integer::CrtCiphertext, smart_crt_sub_parallelized));
impl_smart_assign_op_for_tfhe_integer_server_key!(SmartMulAssign(smart_mul_assign) => (crate::integer::CrtCiphertext, smart_crt_mul_assign_parallelized));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartAdd(smart_add) => (crate::integer::CrtCiphertext, smart_crt_scalar_add));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartSub(smart_sub) => (crate::integer::CrtCiphertext, smart_crt_scalar_sub));
impl_smart_scalar_op_for_tfhe_integer_server_key!(SmartMul(smart_mul) => (crate::integer::CrtCiphertext, smart_crt_scalar_mul));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartAddAssign(smart_add_assign) => (crate::integer::CrtCiphertext, smart_crt_scalar_add_assign));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartSubAssign(smart_sub_assign) => (crate::integer::CrtCiphertext, smart_crt_scalar_sub_assign));
impl_smart_scalar_assign_op_for_tfhe_integer_server_key!(SmartMulAssign(smart_mul_assign) => (crate::integer::CrtCiphertext, smart_crt_scalar_mul_assign));
impl SmartNeg<&mut crate::integer::CrtCiphertext> for crate::integer::ServerKey {
type Output = crate::integer::CrtCiphertext;
fn smart_neg(&self, lhs: &mut crate::integer::CrtCiphertext) -> Self::Output {
self.smart_crt_neg_parallelized(lhs)
}
}
impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn!(SmartAddAssign(smart_add_assign) => smart_scalar_add_assign_parallelized);
impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn!(SmartSubAssign(smart_sub_assign) => smart_scalar_sub_assign_parallelized);
impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn!(SmartMulAssign(smart_mul_assign) => smart_scalar_mul_assign_parallelized);
impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn!(SmartShlAssign(smart_shl_assign) => unchecked_scalar_left_shift_assign_parallelized);
impl_smart_scalar_assign_op_for_tfhe_integer_server_key_dyn!(SmartShrAssign(smart_shr_assign) => unchecked_scalar_right_shift_assign_parallelized);

View File

@@ -5,14 +5,10 @@ use std::ops::{
Neg, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
};
use crate::integer::wopbs::WopbsKey;
use crate::integer::{CrtCiphertext, RadixCiphertextBig, U256};
use crate::integer::U256;
use crate::typed_api::global_state::WithGlobalKey;
use crate::typed_api::integers::client_key::GenericIntegerClientKey;
use crate::typed_api::integers::parameters::{
CrtRepresentation, IntegerParameter, RadixRepresentation, StaticCrtParameter,
StaticIntegerParameter, StaticRadixParameter,
};
use crate::typed_api::integers::parameters::IntegerParameter;
use crate::typed_api::integers::public_key::GenericIntegerPublicKey;
use crate::typed_api::integers::server_key::{
GenericIntegerServerKey, SmartAdd, SmartAddAssign, SmartBitAnd, SmartBitAndAssign, SmartBitOr,
@@ -76,7 +72,7 @@ impl<P> FheDecrypt<u64> for GenericInteger<P>
where
P: IntegerParameter,
P::Id: RefKeyFromKeyChain<Key = GenericIntegerClientKey<P>>,
P::InnerClientKey: DecryptionKey<u64, Ciphertext = P::InnerCiphertext>,
P::InnerClientKey: DecryptionKey<P::InnerCiphertext, u64>,
{
fn decrypt(&self, key: &ClientKey) -> u64 {
let key = self.id.unwrapped_ref_key(key);
@@ -88,7 +84,7 @@ impl<P> FheDecrypt<U256> for GenericInteger<P>
where
P: IntegerParameter,
P::Id: RefKeyFromKeyChain<Key = GenericIntegerClientKey<P>>,
P::InnerClientKey: DecryptionKey<U256, Ciphertext = P::InnerCiphertext>,
P::InnerClientKey: DecryptionKey<P::InnerCiphertext, U256>,
{
fn decrypt(&self, key: &ClientKey) -> U256 {
let key = self.id.unwrapped_ref_key(key);
@@ -99,9 +95,9 @@ where
impl<P, T> FheTryEncrypt<T, ClientKey> for GenericInteger<P>
where
T: Into<U256>,
P: StaticIntegerParameter,
P: IntegerParameter,
P::Id: RefKeyFromKeyChain<Key = GenericIntegerClientKey<P>> + Default,
P::InnerClientKey: EncryptionKey<U256, Ciphertext = P::InnerCiphertext>,
P::InnerClientKey: EncryptionKey<U256, P::InnerCiphertext>,
{
type Error = crate::typed_api::errors::Error;
@@ -117,9 +113,9 @@ where
impl<P, T> FheTryEncrypt<T, PublicKey> for GenericInteger<P>
where
T: Into<U256>,
P: StaticIntegerParameter,
P: IntegerParameter,
P::Id: RefKeyFromPublicKeyChain<Key = GenericIntegerPublicKey<P>> + Default,
P::InnerPublicKey: EncryptionKey<U256, Ciphertext = P::InnerCiphertext>,
P::InnerPublicKey: EncryptionKey<U256, P::InnerCiphertext>,
{
type Error = crate::typed_api::errors::Error;
@@ -343,157 +339,22 @@ where
}
}
// This extra trait is needed as otherwise
//
// impl<P> FheBootstrap for GenericInteger<P>
// where P: StaticCrtParameters,
// P: IntegerParameter<InnerCiphertext=CrtCiphertext>,
// { /* sutff */ }
//
// impl<P> FheBootstrap for GenericInteger<P>
// where P: StaticRadixParameters,
// P: IntegerParameter<InnerCiphertext=RadixCiphertext>,
// P::Id: WithGlobalKey<Key=GenericIntegerServerKey<P>>,
// { /* sutff */ }
//
// Leads to errors about conflicting impl
pub trait WopbsExecutor<
P: StaticIntegerParameter,
R = <P as StaticIntegerParameter>::Representation,
>
{
fn execute_wopbs<F: Fn(u64) -> u64>(
&self,
ct_in: &GenericInteger<P>,
func: F,
) -> GenericInteger<P>;
fn execute_bivariate_wopbs<F: Fn(u64, u64) -> u64>(
&self,
lhs: &GenericInteger<P>,
rhs: &GenericInteger<P>,
func: F,
) -> GenericInteger<P>;
}
pub(crate) fn wopbs_radix(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
ct_in: &RadixCiphertextBig,
func: impl Fn(u64) -> u64,
) -> RadixCiphertextBig {
let switched_ct = wopbs_key.keyswitch_to_wopbs_params(server_key, ct_in);
let luts = wopbs_key.generate_lut_radix(&switched_ct, func);
let res = wopbs_key.wopbs(&switched_ct, luts.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn bivariate_wopbs_radix(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
lhs: &RadixCiphertextBig,
rhs: &RadixCiphertextBig,
func: impl Fn(u64, u64) -> u64,
) -> RadixCiphertextBig {
let switched_lhs = wopbs_key.keyswitch_to_wopbs_params(server_key, lhs);
let switched_rhs = wopbs_key.keyswitch_to_wopbs_params(server_key, rhs);
let lut = wopbs_key.generate_lut_bivariate_radix(&switched_lhs, &switched_rhs, func);
let res = wopbs_key.bivariate_wopbs_with_degree(&switched_lhs, &switched_rhs, lut.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn wopbs_crt(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
ct_in: &CrtCiphertext,
func: impl Fn(u64) -> u64,
) -> CrtCiphertext {
let switched_ct = wopbs_key.keyswitch_to_wopbs_params(server_key, ct_in);
let luts = wopbs_key.generate_lut_crt(&switched_ct, func);
let res = wopbs_key.wopbs(&switched_ct, luts.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
pub(crate) fn bivariate_wopbs_crt(
wopbs_key: &WopbsKey,
server_key: &crate::integer::ServerKey,
lhs: &CrtCiphertext,
rhs: &CrtCiphertext,
func: impl Fn(u64, u64) -> u64,
) -> CrtCiphertext {
let switched_lhs = wopbs_key.keyswitch_to_wopbs_params(server_key, lhs);
let switched_rhs = wopbs_key.keyswitch_to_wopbs_params(server_key, rhs);
let lut = wopbs_key.generate_lut_bivariate_crt(&switched_lhs, &switched_rhs, func);
let res = wopbs_key.bivariate_wopbs_native_crt(&switched_lhs, &switched_rhs, lut.as_slice());
wopbs_key.keyswitch_to_pbs_params(&res)
}
impl<P> WopbsExecutor<P, RadixRepresentation> for GenericIntegerServerKey<P>
where
P: StaticRadixParameter,
{
fn execute_wopbs<F: Fn(u64) -> u64>(
&self,
ct_in: &GenericInteger<P>,
func: F,
) -> GenericInteger<P> {
let ct = ct_in.ciphertext.borrow();
let res = wopbs_radix(&self.wopbs_key, &self.inner, &ct, func);
GenericInteger::<P>::new(res, ct_in.id)
}
fn execute_bivariate_wopbs<F: Fn(u64, u64) -> u64>(
&self,
lhs: &GenericInteger<P>,
rhs: &GenericInteger<P>,
func: F,
) -> GenericInteger<P> {
let lhs_ct = lhs.ciphertext.borrow();
let rhs_ct = rhs.ciphertext.borrow();
let res_ct = bivariate_wopbs_radix(&self.wopbs_key, &self.inner, &lhs_ct, &rhs_ct, func);
GenericInteger::<P>::new(res_ct, lhs.id)
}
}
impl<P> WopbsExecutor<P, CrtRepresentation> for GenericIntegerServerKey<P>
where
P: StaticCrtParameter,
{
fn execute_wopbs<F: Fn(u64) -> u64>(
&self,
ct_in: &GenericInteger<P>,
func: F,
) -> GenericInteger<P> {
let ct = ct_in.ciphertext.borrow();
let res = wopbs_crt(&self.wopbs_key, &self.inner, &ct, func);
GenericInteger::<P>::new(res, ct_in.id)
}
fn execute_bivariate_wopbs<F: Fn(u64, u64) -> u64>(
&self,
lhs: &GenericInteger<P>,
rhs: &GenericInteger<P>,
func: F,
) -> GenericInteger<P> {
let lhs_ct = lhs.ciphertext.borrow();
let rhs_ct = rhs.ciphertext.borrow();
let res_ct = bivariate_wopbs_crt(&self.wopbs_key, &self.inner, &lhs_ct, &rhs_ct, func);
GenericInteger::<P>::new(res_ct, lhs.id)
}
}
impl<P> FheBootstrap for GenericInteger<P>
where
P: StaticIntegerParameter,
P: IntegerParameter,
P::Id: WithGlobalKey<Key = GenericIntegerServerKey<P>>,
GenericIntegerServerKey<P>: WopbsExecutor<P, <P as StaticIntegerParameter>::Representation>,
crate::integer::wopbs::WopbsKey: crate::typed_api::integers::server_key::WopbsEvaluationKey<
P::InnerServerKey,
P::InnerCiphertext,
>,
{
fn map<F: Fn(u64) -> u64>(&self, func: F) -> Self {
self.id
.with_unwrapped_global(|key| key.execute_wopbs(self, func))
use crate::typed_api::integers::server_key::WopbsEvaluationKey;
self.id.with_unwrapped_global(|key| {
let ct = self.ciphertext.borrow();
let res = key.wopbs_key.apply_wopbs(&key.inner, &ct, func);
GenericInteger::<P>::new(res, self.id)
})
}
fn apply<F: Fn(u64) -> u64>(&mut self, func: F) {
@@ -504,16 +365,26 @@ where
impl<P> GenericInteger<P>
where
P: StaticIntegerParameter,
P: IntegerParameter,
P::Id: WithGlobalKey<Key = GenericIntegerServerKey<P>>,
GenericIntegerServerKey<P>: WopbsExecutor<P, <P as StaticIntegerParameter>::Representation>,
crate::integer::wopbs::WopbsKey: crate::typed_api::integers::server_key::WopbsEvaluationKey<
P::InnerServerKey,
P::InnerCiphertext,
>,
{
pub fn bivariate_function<F>(&self, other: &Self, func: F) -> Self
where
F: Fn(u64, u64) -> u64,
{
self.id
.with_unwrapped_global(|key| key.execute_bivariate_wopbs(self, other, func))
self.id.with_unwrapped_global(|key| {
use crate::typed_api::integers::server_key::WopbsEvaluationKey;
let lhs = self.ciphertext.borrow();
let rhs = other.ciphertext.borrow();
let res = key
.wopbs_key
.apply_bivariate_wopbs(&key.inner, &lhs, &rhs, func);
GenericInteger::<P>::new(res, self.id)
})
}
}

View File

@@ -15,14 +15,15 @@ use super::base::GenericInteger;
#[cfg(feature = "internal-keycache")]
use crate::integer::keycache::{KEY_CACHE, KEY_CACHE_WOPBS};
use crate::integer::wopbs::WopbsKey;
use crate::typed_api::internal_traits::ParameterType;
use crate::typed_api::internal_traits::{DecryptionKey, EncryptionKey, ParameterType};
use paste::paste;
macro_rules! define_static_integer_parameters {
(
Radix {
num_bits: $num_bits:literal,
block_parameters: $block_parameters:expr,
big_block_parameters: $big_block_parameters:expr,
small_block_parameters: $small_block_parameters:expr,
num_block: $num_block:literal,
wopbs_block_parameters: $wopbs_block_parameters:expr,
}
@@ -34,24 +35,42 @@ macro_rules! define_static_integer_parameters {
#[doc = concat!("Parameters for the [FheUint", stringify!($num_bits), "] data type.")]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct [<FheUint $num_bits Parameters>](RadixParameters);
pub struct [<FheUint $num_bits Parameters>](pub(in crate::typed_api) RadixParameters);
impl Default for [<FheUint $num_bits Parameters>] {
fn default() -> Self {
Self::big()
}
}
impl [<FheUint $num_bits Parameters>] {
pub fn big() -> Self {
Self(
RadixParameters {
block_parameters: $block_parameters,
block_parameters: $big_block_parameters,
num_block: $num_block,
wopbs_block_parameters: $wopbs_block_parameters,
pbs_order: crate::shortint::PBSOrder::KeyswitchBootstrap,
},
)
}
pub fn small() -> Self {
Self(
RadixParameters {
block_parameters: $small_block_parameters,
num_block: $num_block,
wopbs_block_parameters: $wopbs_block_parameters,
pbs_order: crate::shortint::PBSOrder::BootstrapKeyswitch,
}
)
}
}
impl ParameterType for [<FheUint $num_bits Parameters>] {
type Id = [<FheUint $num_bits Id>];
type InnerCiphertext = crate::integer::RadixCiphertextBig;
type InnerClientKey = crate::integer::RadixClientKey;
type InnerCiphertext = crate::typed_api::integers::server_key::RadixCiphertextDyn;
type InnerClientKey = crate::typed_api::integers::client_key::RadixClientKey;
type InnerPublicKey = crate::typed_api::integers::public_key::RadixPublicKey;
type InnerServerKey = crate::integer::ServerKey;
}
@@ -206,7 +225,8 @@ macro_rules! static_int_type {
num_bits: $num_bits:literal,
keychain_member: $($member:ident).*,
parameters: Radix {
block_parameters: $block_parameters:expr,
big_block_parameters: $big_block_parameters:expr,
small_block_parameters: $small_block_parameters:expr,
num_block: $num_block:literal,
wopbs_block_parameters: $wopbs_block_parameters:expr,
},
@@ -215,7 +235,8 @@ macro_rules! static_int_type {
define_static_integer_parameters!(
Radix {
num_bits: $num_bits,
block_parameters: $block_parameters,
big_block_parameters: $big_block_parameters,
small_block_parameters: $small_block_parameters,
num_block: $num_block,
wopbs_block_parameters: $wopbs_block_parameters,
}
@@ -309,7 +330,8 @@ static_int_type! {
num_bits: 8,
keychain_member: integer_key.uint8_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 4,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -321,7 +343,8 @@ static_int_type! {
num_bits: 10,
keychain_member: integer_key.uint10_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 5,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -333,7 +356,8 @@ static_int_type! {
num_bits: 12,
keychain_member: integer_key.uint12_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 6,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -345,7 +369,8 @@ static_int_type! {
num_bits: 14,
keychain_member: integer_key.uint14_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 7,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -357,7 +382,8 @@ static_int_type! {
num_bits: 16,
keychain_member: integer_key.uint16_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 8,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -369,7 +395,8 @@ static_int_type! {
num_bits: 256,
keychain_member: integer_key.uint256_key,
parameters: Radix {
block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
big_block_parameters: crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2,
small_block_parameters: crate::shortint::parameters::PARAM_SMALL_MESSAGE_2_CARRY_2,
num_block: 128,
wopbs_block_parameters: crate::shortint::parameters::parameters_wopbs_message_carry::WOPBS_PARAM_MESSAGE_2_CARRY_2,
},
@@ -391,7 +418,8 @@ impl FheDecrypt<u8> for FheUint8 {
fn decrypt(&self, key: &ClientKey) -> u8 {
let id = <FheUint8Parameters as ParameterType>::Id::default();
let key = id.unwrapped_ref_key(key);
key.inner.decrypt(&self.ciphertext.borrow()) as u8
let clear: u64 = key.inner.decrypt(&*self.ciphertext.borrow());
clear as u8
}
}
@@ -410,6 +438,7 @@ impl FheDecrypt<u16> for FheUint16 {
fn decrypt(&self, key: &ClientKey) -> u16 {
let id = <FheUint16Parameters as ParameterType>::Id::default();
let key = id.unwrapped_ref_key(key);
key.inner.decrypt(&self.ciphertext.borrow()) as u16
let clear: u64 = key.inner.decrypt(&*self.ciphertext.borrow());
clear as u16
}
}

View File

@@ -1,19 +1,13 @@
/// Trait to be implemented on keys that encrypts clear values into ciphertexts
pub(crate) trait EncryptionKey<ClearType> {
/// The type of ciphertext returned as a result of the encryption
type Ciphertext;
pub(crate) trait EncryptionKey<ClearType, CiphertextType> {
/// The encryption process
fn encrypt(&self, value: ClearType) -> Self::Ciphertext;
fn encrypt(&self, value: ClearType) -> CiphertextType;
}
/// Trait to be implemented on keys that decrypts ciphertext into clear values
pub(crate) trait DecryptionKey<ClearType> {
/// The type of ciphertext that this key decrypts
type Ciphertext;
pub(crate) trait DecryptionKey<CiphertextType, ClearType> {
/// The decryption process
fn decrypt(&self, ciphertext: &Self::Ciphertext) -> ClearType;
fn decrypt(&self, ciphertext: &CiphertextType) -> ClearType;
}
pub trait FromParameters<P> {

View File

@@ -1,12 +1,14 @@
#[cfg(feature = "integer")]
use crate::integer::U256;
use crate::typed_api::prelude::*;
#[cfg(feature = "boolean")]
use crate::typed_api::FheBool;
#[cfg(feature = "shortint")]
use crate::typed_api::FheUint2;
#[cfg(feature = "integer")]
use crate::typed_api::FheUint8;
#[cfg(any(feature = "boolean", feature = "shortint", feature = "integer"))]
use crate::typed_api::{generate_keys, ClientKey, ConfigBuilder, PublicKey};
#[cfg(feature = "integer")]
use crate::typed_api::{FheUint256, FheUint8};
#[cfg(any(feature = "boolean", feature = "shortint", feature = "integer"))]
use std::fmt::Debug;
@@ -66,6 +68,39 @@ fn test_integer_public_key() {
assert_that_public_key_encryption_is_decrypted_by_client_key::<FheUint8, u8>(235, &pks, &cks);
}
#[cfg(feature = "integer")]
#[test]
fn test_small_uint8() {
let config = ConfigBuilder::all_disabled()
.enable_default_uint8_small()
.build();
let (cks, _sks) = generate_keys(config);
let pks = PublicKey::new(&cks);
assert_that_public_key_encryption_is_decrypted_by_client_key::<FheUint8, u8>(235, &pks, &cks);
}
#[cfg(feature = "integer")]
#[test]
fn test_small_uint256() {
let config = ConfigBuilder::all_disabled()
.enable_default_uint256_small()
.build();
let (cks, _sks) = generate_keys(config);
let pks = PublicKey::new(&cks);
use rand::prelude::*;
let mut rng = rand::thread_rng();
let value = rng.gen::<U256>();
assert_that_public_key_encryption_is_decrypted_by_client_key::<FheUint256, U256>(
value, &pks, &cks,
);
}
#[cfg(feature = "boolean")]
#[test]
fn test_with_context() {
@@ -78,5 +113,5 @@ fn test_with_context() {
let (r, _) = crate::typed_api::with_server_key_as_context(sks, move || a & b);
let d = r.decrypt(&cks);
assert!(d);
assert!(!d);
}