pub struct ServerKey { /* private fields */ }
integer
only.Expand description
A structure containing the server public key.
The server key is generated by the client and is meant to be published: the client sends it to the server so it can compute homomorphic integer circuits.
Note: a ServerKey
can be fairly large, if needed you can generate a CompressedServerKey
instead to reduce storage and network bandwidth usage.
Implementations§
Source§impl ServerKey
impl ServerKey
Sourcepub fn par_generate_oblivious_pseudo_random_unsigned_integer(
&self,
seed: Seed,
num_blocks: u64,
) -> RadixCiphertext
pub fn par_generate_oblivious_pseudo_random_unsigned_integer( &self, seed: Seed, num_blocks: u64, ) -> RadixCiphertext
Generates an encrypted num_block
blocks unsigned integer
taken uniformly in its full range using the given seed.
The encryted value is oblivious to the server.
It can be useful to make server random generation deterministic.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::Seed;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let ct_res = sks.par_generate_oblivious_pseudo_random_unsigned_integer(Seed(0), size as u64);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert!(dec_result < 1 << (2 * size));
Sourcepub fn par_generate_oblivious_pseudo_random_unsigned_integer_bounded(
&self,
seed: Seed,
random_bits_count: u64,
num_blocks: u64,
) -> RadixCiphertext
pub fn par_generate_oblivious_pseudo_random_unsigned_integer_bounded( &self, seed: Seed, random_bits_count: u64, num_blocks: u64, ) -> RadixCiphertext
Generates an encrypted num_block
blocks unsigned integer
taken uniformly in [0, 2^random_bits_count[
using the given seed.
The encryted value is oblivious to the server.
It can be useful to make server random generation deterministic.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::Seed;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let random_bits_count = 3;
let ct_res = sks.par_generate_oblivious_pseudo_random_unsigned_integer_bounded(
Seed(0),
random_bits_count,
size as u64,
);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert!(dec_result < (1 << random_bits_count));
Source§impl ServerKey
impl ServerKey
Sourcepub fn par_generate_oblivious_pseudo_random_signed_integer(
&self,
seed: Seed,
num_blocks: u64,
) -> SignedRadixCiphertext
pub fn par_generate_oblivious_pseudo_random_signed_integer( &self, seed: Seed, num_blocks: u64, ) -> SignedRadixCiphertext
Generates an encrypted num_block
blocks signed integer
taken uniformly in its full range using the given seed.
The encryted value is oblivious to the server.
It can be useful to make server random generation deterministic.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::Seed;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let ct_res = sks.par_generate_oblivious_pseudo_random_signed_integer(Seed(0), size as u64);
// Decrypt:
let dec_result: i64 = cks.decrypt_signed(&ct_res);
assert!(dec_result < 1 << (2 * size - 1));
assert!(dec_result >= -(1 << (2 * size - 1)));
Sourcepub fn par_generate_oblivious_pseudo_random_signed_integer_bounded(
&self,
seed: Seed,
random_bits_count: u64,
num_blocks: u64,
) -> SignedRadixCiphertext
pub fn par_generate_oblivious_pseudo_random_signed_integer_bounded( &self, seed: Seed, random_bits_count: u64, num_blocks: u64, ) -> SignedRadixCiphertext
Generates an encrypted num_block
blocks signed integer
taken uniformly in [0, 2^random_bits_count[
using the given seed.
The encryted value is oblivious to the server.
It can be useful to make server random generation deterministic.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::Seed;
let size = 4;
let random_bits_count = 3;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let ct_res = sks.par_generate_oblivious_pseudo_random_signed_integer_bounded(
Seed(0),
random_bits_count,
size as u64,
);
// Decrypt:
let dec_result: i64 = cks.decrypt_signed(&ct_res);
assert!(dec_result >= 0);
assert!(dec_result < (1 << random_bits_count));
Source§impl ServerKey
impl ServerKey
Sourcepub fn smart_crt_add(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &mut CrtCiphertext,
) -> CrtCiphertext
pub fn smart_crt_add( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext
Computes homomorphically an addition between two ciphertexts encrypting integer values.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
sks.smart_crt_add_assign(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
pub fn smart_crt_add_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, )
pub fn is_crt_add_possible( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> Result<(), CheckError>
pub fn unchecked_crt_add_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &CrtCiphertext, )
pub fn unchecked_crt_add( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_mul_assign(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &CrtCiphertext,
)
pub fn unchecked_crt_mul_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &CrtCiphertext, )
Computes homomorphically a multiplication between two ciphertexts encrypting integer values in the CRT decomposition.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 29;
let clear_2 = 23;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_crt_mul_assign(&mut ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn unchecked_crt_mul( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext
Sourcepub fn smart_crt_mul_assign(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &mut CrtCiphertext,
)
pub fn smart_crt_mul_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, )
Computes homomorphically a multiplication between two ciphertexts encrypting integer values in the CRT decomposition.
This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 29;
let clear_2 = 29;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.smart_crt_mul_assign(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn smart_crt_mul( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_neg(&self, ctxt: &CrtCiphertext) -> CrtCiphertext
pub fn unchecked_crt_neg(&self, ctxt: &CrtCiphertext) -> CrtCiphertext
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear = 14_u64;
let mut ctxt = cks.encrypt(clear);
sks.unchecked_crt_neg_assign(&mut ctxt);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!(16, res);
Sourcepub fn unchecked_crt_neg_assign(&self, ctxt: &mut CrtCiphertext)
pub fn unchecked_crt_neg_assign(&self, ctxt: &mut CrtCiphertext)
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
Sourcepub fn smart_crt_neg_assign(&self, ctxt: &mut CrtCiphertext)
pub fn smart_crt_neg_assign(&self, ctxt: &mut CrtCiphertext)
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear = 14_u64;
let mut ctxt = cks.encrypt(clear);
sks.smart_crt_neg_assign(&mut ctxt);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!(16, res);
pub fn smart_crt_neg(&self, ctxt: &mut CrtCiphertext) -> CrtCiphertext
pub fn is_crt_neg_possible( &self, ctxt: &CrtCiphertext, ) -> Result<(), CheckError>
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_add(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_add( &self, ct: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_add_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn unchecked_crt_scalar_add_assign(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
)
pub fn unchecked_crt_scalar_add_assign( &self, ct: &mut CrtCiphertext, scalar: u64, )
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
Sourcepub fn is_crt_scalar_add_possible(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn is_crt_scalar_add_possible( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Verifies if a scalar can be added to a ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
sks.is_crt_scalar_add_possible(&ctxt_1, clear_2).unwrap();
Sourcepub fn checked_crt_scalar_add(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_add( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_add_assign(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn checked_crt_scalar_add_assign(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_add_assign( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
Sourcepub fn smart_crt_scalar_add(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_add( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically the addition of ciphertext with a scalar.
The result is returned in a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt = sks.smart_crt_scalar_add(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn smart_crt_scalar_add_assign(&self, ct: &mut CrtCiphertext, scalar: u64)
pub fn smart_crt_scalar_add_assign(&self, ct: &mut CrtCiphertext, scalar: u64)
Computes homomorphically the addition of ciphertext with a scalar.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_add_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_mul(
&self,
ctxt: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_mul( &self, ctxt: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 2;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_mul_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn unchecked_crt_scalar_mul_assign( &self, ctxt: &mut CrtCiphertext, scalar: u64, )
Sourcepub fn is_crt_scalar_mul_possible(
&self,
ctxt: &CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn is_crt_scalar_mul_possible( &self, ctxt: &CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Verifies if ct1 can be multiplied by scalar.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 2;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
sks.is_crt_scalar_mul_possible(&ctxt_1, clear_2).unwrap();
Sourcepub fn checked_crt_scalar_mul(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_mul( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 2;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_mul_assign(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
Sourcepub fn checked_crt_scalar_mul_assign(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_mul_assign( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is assigned to the ciphertext given as parameter. Otherwise a CheckError is returned.
Sourcepub fn smart_crt_scalar_mul(
&self,
ctxt: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_mul( &self, ctxt: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar value shall fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt = sks.smart_crt_scalar_mul(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 * clear_2) % modulus, res);
Sourcepub fn smart_crt_scalar_mul_assign(&self, ctxt: &mut CrtCiphertext, scalar: u64)
pub fn smart_crt_scalar_mul_assign(&self, ctxt: &mut CrtCiphertext, scalar: u64)
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar shall value fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is assigned to the input ciphertext
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_mul_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn is_crt_small_scalar_mul_possible( &self, ctxt: &CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_sub(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_sub( &self, ct: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a subtraction between a ciphertext and a scalar.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_sub_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
pub fn unchecked_crt_scalar_sub_assign( &self, ct: &mut CrtCiphertext, scalar: u64, )
Sourcepub fn is_crt_scalar_sub_possible(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn is_crt_scalar_sub_possible( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Verifies if the subtraction of a ciphertext by scalar can be computed.
§Example
use tfhe::integer::gen_keys_crt;
let basis = vec![2, 3, 5];
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
sks.is_crt_scalar_sub_possible(&ctxt_1, clear_2).unwrap();
// Decrypt
let res = cks.decrypt(&ctxt_1);
Sourcepub fn checked_crt_scalar_sub(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_sub( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 8;
let ctxt_1 = cks.encrypt(clear_1);
let ct_res = sks.checked_crt_scalar_sub(&ctxt_1, clear_2).unwrap();
// Decrypt:
let dec = cks.decrypt(&ct_res);
assert_eq!((clear_1 - clear_2) % modulus, dec);
Sourcepub fn checked_crt_scalar_sub_assign(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_sub_assign( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_sub_assign(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt:
let dec = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, dec);
Sourcepub fn smart_crt_scalar_sub(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_sub( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a subtraction of a ciphertext by a scalar.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_sub_assign(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
pub fn smart_crt_scalar_sub_assign(&self, ct: &mut CrtCiphertext, scalar: u64)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_sub(
&self,
ctxt_left: &CrtCiphertext,
ctxt_right: &CrtCiphertext,
) -> CrtCiphertext
pub fn unchecked_crt_sub( &self, ctxt_left: &CrtCiphertext, ctxt_right: &CrtCiphertext, ) -> CrtCiphertext
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.unchecked_crt_sub(&ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn unchecked_crt_sub_assign(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &CrtCiphertext,
)
pub fn unchecked_crt_sub_assign( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &CrtCiphertext, )
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.unchecked_crt_sub(&ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn smart_crt_sub(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &mut CrtCiphertext,
) -> CrtCiphertext
pub fn smart_crt_sub( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &mut CrtCiphertext, ) -> CrtCiphertext
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.smart_crt_sub(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn smart_crt_sub_assign(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &mut CrtCiphertext,
)
pub fn smart_crt_sub_assign( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &mut CrtCiphertext, )
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
sks.smart_crt_sub_assign(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
pub fn is_crt_sub_possible( &self, ctxt_left: &CrtCiphertext, ctxt_right: &CrtCiphertext, ) -> Result<(), CheckError>
Source§impl ServerKey
impl ServerKey
Sourcepub fn full_extract_message_assign(&self, ctxt: &mut CrtCiphertext)
pub fn full_extract_message_assign(&self, ctxt: &mut CrtCiphertext)
Extract all the messages.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_crt_add_assign(&mut ctxt_1, &ctxt_2);
sks.full_extract_message_assign(&mut ctxt_1);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn pbs_crt_compliant_function_assign<F>(
&self,
ct1: &mut CrtCiphertext,
f: F,
)
pub fn pbs_crt_compliant_function_assign<F>( &self, ct1: &mut CrtCiphertext, f: F, )
Computes a PBS for CRT-compliant functions.
§Warning
This allows to compute programmable bootstrapping over integers under the condition that the function is said to be CRT-compliant. This means that the function should be correct when evaluated on each modular block independently (e.g. arithmetic functions).
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 28;
let mut ctxt_1 = cks.encrypt(clear_1);
// Compute homomorphically the crt-compliant PBS
sks.pbs_crt_compliant_function_assign(&mut ctxt_1, |x| x * x * x);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_1 * clear_1) % modulus, res);
pub fn pbs_crt_compliant_function<F>( &self, ct1: &CrtCiphertext, f: F, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_add_assign_parallelized(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &CrtCiphertext,
)
pub fn unchecked_crt_add_assign_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &CrtCiphertext, )
Computes homomorphically an addition between two ciphertexts encrypting integer values in the CRT decomposition.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_crt_add_assign_parallelized(&mut ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
pub fn unchecked_crt_add_parallelized( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext
Sourcepub fn smart_crt_add_assign_parallelized(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &mut CrtCiphertext,
)
pub fn smart_crt_add_assign_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, )
Computes homomorphically an addition between two ciphertexts encrypting integer values in the CRT decomposition.
This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 29;
let clear_2 = 29;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.smart_crt_add_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
pub fn smart_crt_add_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_mul_assign_parallelized(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &CrtCiphertext,
)
pub fn unchecked_crt_mul_assign_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &CrtCiphertext, )
Computes homomorphically a multiplication between two ciphertexts encrypting integer values in the CRT decomposition.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 29;
let clear_2 = 23;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_crt_mul_assign_parallelized(&mut ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn unchecked_crt_mul_parallelized( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext
Sourcepub fn smart_crt_mul_assign_parallelized(
&self,
ct_left: &mut CrtCiphertext,
ct_right: &mut CrtCiphertext,
)
pub fn smart_crt_mul_assign_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, )
Computes homomorphically a multiplication between two ciphertexts encrypting integer values in the CRT decomposition.
This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 29;
let clear_2 = 29;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.smart_crt_mul_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn smart_crt_mul_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_neg_parallelized(
&self,
ctxt: &CrtCiphertext,
) -> CrtCiphertext
pub fn unchecked_crt_neg_parallelized( &self, ctxt: &CrtCiphertext, ) -> CrtCiphertext
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear = 14_u64;
let mut ctxt = cks.encrypt(clear);
sks.unchecked_crt_neg_assign_parallelized(&mut ctxt);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!(16, res);
Sourcepub fn unchecked_crt_neg_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
pub fn unchecked_crt_neg_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
Sourcepub fn smart_crt_neg_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
pub fn smart_crt_neg_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear = 14_u64;
let mut ctxt = cks.encrypt(clear);
sks.smart_crt_neg_assign_parallelized(&mut ctxt);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!(16, res);
pub fn smart_crt_neg_parallelized( &self, ctxt: &mut CrtCiphertext, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_add_parallelized(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_add_parallelized( &self, ct: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_add_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn unchecked_crt_scalar_add_assign_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
)
pub fn unchecked_crt_scalar_add_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
Sourcepub fn checked_crt_scalar_add_parallelized(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_add_parallelized( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_add_assign_parallelized(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn checked_crt_scalar_add_assign_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_add_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
Sourcepub fn smart_crt_scalar_add_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_add_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically the addition of ciphertext with a scalar.
The result is returned in a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt = sks.smart_crt_scalar_add_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn smart_crt_scalar_add_assign_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
)
pub fn smart_crt_scalar_add_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )
Computes homomorphically the addition of ciphertext with a scalar.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_add_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_mul_parallelized(
&self,
ctxt: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_mul_parallelized( &self, ctxt: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 2;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_mul_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
pub fn unchecked_crt_scalar_mul_assign_parallelized( &self, ctxt: &mut CrtCiphertext, scalar: u64, )
Sourcepub fn checked_crt_scalar_mul_parallelized(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_mul_parallelized( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 2;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_mul_assign_parallelized(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
Sourcepub fn checked_crt_scalar_mul_assign_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_mul_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is assigned to the ciphertext given as parameter. Otherwise a CheckError is returned.
Sourcepub fn smart_crt_scalar_mul_parallelized(
&self,
ctxt: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_mul_parallelized( &self, ctxt: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar value shall fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt = sks.smart_crt_scalar_mul_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 * clear_2) % modulus, res);
Sourcepub fn smart_crt_scalar_mul_assign_parallelized(
&self,
ctxt: &mut CrtCiphertext,
scalar: u64,
)
pub fn smart_crt_scalar_mul_assign_parallelized( &self, ctxt: &mut CrtCiphertext, scalar: u64, )
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar shall value fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is assigned to the input ciphertext
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_mul_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_2) % modulus, res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_scalar_sub_parallelized(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn unchecked_crt_scalar_sub_parallelized( &self, ct: &CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a subtraction between a ciphertext and a scalar.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.unchecked_crt_scalar_sub_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
pub fn unchecked_crt_scalar_sub_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )
Sourcepub fn checked_crt_scalar_sub_parallelized(
&self,
ct: &CrtCiphertext,
scalar: u64,
) -> Result<CrtCiphertext, CheckError>
pub fn checked_crt_scalar_sub_parallelized( &self, ct: &CrtCiphertext, scalar: u64, ) -> Result<CrtCiphertext, CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 8;
let ctxt_1 = cks.encrypt(clear_1);
let ct_res = sks
.checked_crt_scalar_sub_parallelized(&ctxt_1, clear_2)
.unwrap();
// Decrypt:
let dec = cks.decrypt(&ct_res);
assert_eq!((clear_1 - clear_2) % modulus, dec);
Sourcepub fn checked_crt_scalar_sub_assign_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_crt_scalar_sub_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
let mut ctxt_1 = cks.encrypt(clear_1);
sks.checked_crt_scalar_sub_assign_parallelized(&mut ctxt_1, clear_2)
.unwrap();
// Decrypt:
let dec = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, dec);
Sourcepub fn smart_crt_scalar_sub_parallelized(
&self,
ct: &mut CrtCiphertext,
scalar: u64,
) -> CrtCiphertext
pub fn smart_crt_scalar_sub_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, ) -> CrtCiphertext
Computes homomorphically a subtraction of a ciphertext by a scalar.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 7;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
sks.smart_crt_scalar_sub_assign_parallelized(&mut ctxt_1, clear_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
pub fn smart_crt_scalar_sub_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_crt_sub_parallelized(
&self,
ctxt_left: &CrtCiphertext,
ctxt_right: &CrtCiphertext,
) -> CrtCiphertext
pub fn unchecked_crt_sub_parallelized( &self, ctxt_left: &CrtCiphertext, ctxt_right: &CrtCiphertext, ) -> CrtCiphertext
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.unchecked_crt_sub_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn unchecked_crt_sub_assign_parallelized(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &CrtCiphertext,
)
pub fn unchecked_crt_sub_assign_parallelized( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &CrtCiphertext, )
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.unchecked_crt_sub_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn smart_crt_sub_parallelized(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &mut CrtCiphertext,
) -> CrtCiphertext
pub fn smart_crt_sub_parallelized( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &mut CrtCiphertext, ) -> CrtCiphertext
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
let ctxt = sks.smart_crt_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt);
assert_eq!((clear_1 - clear_2) % modulus, res);
Sourcepub fn smart_crt_sub_assign_parallelized(
&self,
ctxt_left: &mut CrtCiphertext,
ctxt_right: &mut CrtCiphertext,
)
pub fn smart_crt_sub_assign_parallelized( &self, ctxt_left: &mut CrtCiphertext, ctxt_right: &mut CrtCiphertext, )
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 5;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
sks.smart_crt_sub_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 - clear_2) % modulus, res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn full_extract_message_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
pub fn full_extract_message_assign_parallelized(&self, ctxt: &mut CrtCiphertext)
Extract all the messages.
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 14;
let clear_2 = 14;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_crt_add_assign(&mut ctxt_1, &ctxt_2);
sks.full_extract_message_assign_parallelized(&mut ctxt_1);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 + clear_2) % modulus, res);
Sourcepub fn pbs_crt_compliant_function_assign_parallelized<F>(
&self,
ct1: &mut CrtCiphertext,
f: F,
)
pub fn pbs_crt_compliant_function_assign_parallelized<F>( &self, ct1: &mut CrtCiphertext, f: F, )
Computes a PBS for CRT-compliant functions.
§Warning
This allows to compute programmable bootstrapping over integers under the condition that the function is said to be CRT-compliant. This means that the function should be correct when evaluated on each modular block independently (e.g. arithmetic functions).
§Example
use tfhe::integer::gen_keys_crt;
use tfhe::shortint::parameters::PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let basis = vec![2, 3, 5];
let modulus: u64 = basis.iter().product();
let (cks, sks) = gen_keys_crt(PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128, basis);
let clear_1 = 28;
let mut ctxt_1 = cks.encrypt(clear_1);
// Compute homomorphically the crt-compliant PBS
sks.pbs_crt_compliant_function_assign_parallelized(&mut ctxt_1, |x| x * x * x);
// Decrypt
let res = cks.decrypt(&ctxt_1);
assert_eq!((clear_1 * clear_1 * clear_1) % modulus, res);
pub fn pbs_crt_compliant_function_parallelized<F>( &self, ct1: &CrtCiphertext, f: F, ) -> CrtCiphertext
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_add<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_add<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 10;
let msg2 = 127;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.unchecked_add(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 + msg2);
Sourcepub fn unchecked_add_assign<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_add_assign<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 28;
let msg2 = 127;
let mut ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
sks.unchecked_add_assign(&mut ct1, &ct2);
// Decrypt:
let dec_ct1: u64 = cks.decrypt(&ct1);
assert_eq!(dec_ct1, msg1 + msg2);
Sourcepub fn is_add_possible<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn is_add_possible<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Verifies if ct1 and ct2 can be added together.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 46u64;
let msg2 = 87u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Check if we can perform an addition
sks.is_add_possible(&ct1, &ct2).unwrap();
Sourcepub fn checked_add<T>(&self, ct_left: &T, ct_right: &T) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_add<T>(&self, ct_left: &T, ct_right: &T) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 41;
let msg2 = 101;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.checked_add(&ct1, &ct2);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(msg1 + msg2, clear);
}
}
Sourcepub fn checked_add_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_add_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 41;
let msg2 = 101;
let mut ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
sks.checked_add_assign(&mut ct1, &ct2).unwrap();
let clear: u64 = cks.decrypt(&ct1);
assert_eq!(msg1 + msg2, clear);
Sourcepub fn smart_add<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_add<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.smart_add(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 + msg2);
pub fn smart_add_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)where
T: IntegerRadixCiphertext,
pub fn unchecked_signed_overflowing_add( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_bitand<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitand<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically bitand between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 201u64;
let msg2 = 1u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically a bitwise and:
let ct_res = sks.unchecked_bitand(&ct1, &ct2);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(dec, msg1 & msg2);
pub fn unchecked_bitand_assign<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn is_functional_bivariate_pbs_possible<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerCiphertext,
pub fn is_functional_bivariate_pbs_possible<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerCiphertext,
Verifies if a bivariate functional pbs can be applied on ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 46u64;
let msg2 = 87u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
sks.is_functional_bivariate_pbs_possible(&ct1, &ct2)
.unwrap();
Sourcepub fn checked_bitand<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitand<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.checked_bitand(&ct1, &ct2);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(msg1 & msg2, clear);
}
}
Sourcepub fn checked_bitand_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitand_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let mut ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
sks.checked_bitand_assign(&mut ct1, &ct2).unwrap();
let clear: u64 = cks.decrypt(&ct1);
assert_eq!(msg1 & msg2, clear);
Sourcepub fn smart_bitand<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitand<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitand(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 & msg2);
pub fn smart_bitand_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)where
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_bitor<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitor<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically bitor between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 200;
let msg2 = 1;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically a bitwise or:
let ct_res = sks.unchecked_bitor(&ct1, &ct2);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(dec, msg1 | msg2);
pub fn unchecked_bitor_assign<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn checked_bitor<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitor<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitor between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.checked_bitor(&ct1, &ct2);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(msg1 | msg2, clear);
}
}
Sourcepub fn checked_bitor_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitor_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let mut ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
sks.checked_bitor_assign(&mut ct1, &ct2).unwrap();
let clear: u64 = cks.decrypt(&ct1);
assert_eq!(msg1 | msg2, clear);
Sourcepub fn smart_bitor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitor between two ciphertexts encrypting integer values.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 | msg2);
pub fn smart_bitor_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)where
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_bitxor<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitxor<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically bitxor between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 49;
let msg2 = 64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically a bitwise xor:
let ct_res = sks.unchecked_bitxor(&ct1, &ct2);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg1 ^ msg2, dec);
pub fn unchecked_bitxor_assign<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn checked_bitxor<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitxor<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.checked_bitxor(&ct1, &ct2);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(msg1 ^ msg2, clear);
}
}
Sourcepub fn checked_bitxor_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_bitxor_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 41;
let msg2 = 101;
let mut ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
sks.checked_bitxor_assign(&mut ct1, &ct2).unwrap();
let clear: u64 = cks.decrypt(&ct1);
assert_eq!(msg1 ^ msg2, clear);
Sourcepub fn smart_bitxor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitxor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitxor(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 ^ msg2);
pub fn smart_bitxor_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)where
T: IntegerRadixCiphertext,
Sourcepub fn boolean_bitand(
&self,
lhs: &BooleanBlock,
rhs: &BooleanBlock,
) -> BooleanBlock
pub fn boolean_bitand( &self, lhs: &BooleanBlock, rhs: &BooleanBlock, ) -> BooleanBlock
Computes homomorphically a bitand between two boolean ciphertexts
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 14u8;
let ct = cks.encrypt(msg);
let ct_is_ge = sks.scalar_ge_parallelized(&ct, 10);
let ct_is_le = sks.scalar_le_parallelized(&ct, 15);
let ct_is_in_range = sks.boolean_bitand(&ct_is_ge, &ct_is_le);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_is_in_range);
assert_eq!(dec_result, (10..=15).contains(&msg));
pub fn boolean_bitand_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)
Sourcepub fn boolean_bitor(
&self,
lhs: &BooleanBlock,
rhs: &BooleanBlock,
) -> BooleanBlock
pub fn boolean_bitor( &self, lhs: &BooleanBlock, rhs: &BooleanBlock, ) -> BooleanBlock
Computes homomorphically a bitor between two boolean ciphertexts
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 14u8;
let ct = cks.encrypt(msg);
let ct_is_ge = sks.scalar_ge_parallelized(&ct, 10);
let ct_is_le = sks.scalar_le_parallelized(&ct, 15);
let ct_final_condition = sks.boolean_bitor(&ct_is_ge, &ct_is_le);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_final_condition);
assert_eq!(dec_result, msg >= 10 || msg <= 15);
pub fn boolean_bitor_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)
Sourcepub fn boolean_bitxor(
&self,
lhs: &BooleanBlock,
rhs: &BooleanBlock,
) -> BooleanBlock
pub fn boolean_bitxor( &self, lhs: &BooleanBlock, rhs: &BooleanBlock, ) -> BooleanBlock
Computes homomorphically a bitxor between two boolean ciphertexts
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 14u8;
let ct = cks.encrypt(msg);
let ct_is_ge = sks.scalar_ge_parallelized(&ct, 10);
let ct_is_le = sks.scalar_le_parallelized(&ct, 15);
let ct_final_condition = sks.boolean_bitxor(&ct_is_ge, &ct_is_le);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_final_condition);
assert_eq!(dec_result, ((msg >= 10) ^ (msg <= 15)));
pub fn boolean_bitxor_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)
Sourcepub fn boolean_bitnot(&self, boolean_block: &BooleanBlock) -> BooleanBlock
pub fn boolean_bitnot(&self, boolean_block: &BooleanBlock) -> BooleanBlock
Computes homomorphically the bitnot of a boolean block
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = true;
let ct = cks.encrypt_bool(msg);
let ct_res = sks.boolean_bitnot(&ct);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, !msg);
pub fn boolean_bitnot_assign(&self, boolean_block: &mut BooleanBlock)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_eq<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_eq<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares for equality 2 ciphertexts
Returns a ciphertext containing 1 if lhs == rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_eq(&ct1, &ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 == msg2);
pub fn unchecked_ne<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_gt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_gt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is strictly greater than rhs
Returns a ciphertext containing 1 if lhs > rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_gt(&ct1, &ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 > msg2);
Sourcepub fn unchecked_ge<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_ge<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is greater or equal than rhs
Returns a ciphertext containing 1 if lhs >= rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 97u64;
let msg2 = 97u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_ge(&ct1, &ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 >= msg2);
Sourcepub fn unchecked_lt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_lt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is strictly lower than rhs
Returns a ciphertext containing 1 if lhs < rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 237u64;
let msg2 = 23u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_lt(&ct1, &ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 < msg2);
Sourcepub fn unchecked_le<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_le<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is lower or equal than rhs
Returns a ciphertext containing 1 if lhs < rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 237u64;
let msg2 = 23u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_le(&ct1, &ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 < msg2);
Sourcepub fn unchecked_max<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_max<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes the max of two encrypted values
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 237u64;
let msg2 = 23u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_max(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, std::cmp::max(msg1, msg2));
Sourcepub fn unchecked_min<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_min<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes the min of two encrypted values
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 237u64;
let msg2 = 23u64;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.unchecked_min(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, std::cmp::min(msg1, msg2));
Sourcepub fn smart_eq<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_eq<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares for equality 2 ciphertexts
Returns a ciphertext containing 1 if lhs == rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_eq(&mut ct1, &mut ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 == msg2);
pub fn smart_ne<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_gt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_gt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is strictly greater than rhs
Returns a ciphertext containing 1 if lhs == rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_gt(&mut ct1, &mut ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 > msg2);
Sourcepub fn smart_ge<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_ge<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is greater or equal than rhs
Returns a ciphertext containing 1 if lhs >= rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_gt(&mut ct1, &mut ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 >= msg2);
Sourcepub fn smart_lt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_lt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is strictly lower than rhs
Returns a ciphertext containing 1 if lhs < rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_lt(&mut ct1, &mut ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 < msg2);
Sourcepub fn smart_le<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_le<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares if lhs is lower or equal than rhs
Returns a ciphertext containing 1 if lhs <= rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_le(&mut ct1, &mut ct2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 <= msg2);
Sourcepub fn smart_max<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_max<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes the max of two encrypted values
Returns a ciphertext containing 1 if lhs < rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_max(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, std::cmp::max(msg1, msg2));
Sourcepub fn smart_min<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_min<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes the min of two encrypted values
Returns a ciphertext containing 1 if lhs < rhs, otherwise 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_min(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, std::cmp::min(msg1, msg2));
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_block_mul_assign<T>(
&self,
ct_left: &mut T,
ct_right: &Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
pub fn unchecked_block_mul_assign<T>(
&self,
ct_left: &mut T,
ct_right: &Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertext encrypting an integer value and another encrypting a shortint value.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let clear_1 = 170;
let clear_2 = 3;
// Encrypt two messages
let mut ct_left = cks.encrypt(clear_1);
let ct_right = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_block_mul_assign(&mut ct_left, &ct_right, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_left);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn unchecked_block_mul<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_block_mul<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertexts encrypting an integer value and another encrypting a shortint value.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let clear_1 = 55;
let clear_2 = 3;
// Encrypt two messages
let ct_left = cks.encrypt(clear_1);
let ct_right = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.unchecked_block_mul(&ct_left, &ct_right, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn smart_block_mul<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_block_mul<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertext encrypting integer value and another encrypting a shortint value.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let clear_1 = 170;
let clear_2 = 3;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.smart_block_mul(&mut ctxt_1, &mut ctxt_2, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
pub fn smart_block_mul_assign<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_mul_assign<T>(&self, ct1: &mut T, ct2: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_mul_assign<T>(&self, ct1: &mut T, ct2: &T)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let clear_1 = 255;
let clear_2 = 143;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.unchecked_mul(&ctxt_1, &ctxt_2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn unchecked_mul<T>(&self, ct1: &T, ct2: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_mul<T>(&self, ct1: &T, ct2: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
Sourcepub fn smart_mul_assign<T>(&self, ct1: &mut T, ct2: &mut T)where
T: IntegerRadixCiphertext,
pub fn smart_mul_assign<T>(&self, ct1: &mut T, ct2: &mut T)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let clear_1 = 170;
let clear_2 = 6;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.smart_mul(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn smart_mul<T>(&self, ct1: &mut T, ct2: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_mul<T>(&self, ct1: &mut T, ct2: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
The result is returned as a new ciphertext.
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_neg<T>(&self, ctxt: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_neg<T>(&self, ctxt: &T) -> Twhere
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
// Encrypt two messages:
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let modulus = 1 << 8;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 159u64;
// Encrypt a message
let mut ctxt = cks.encrypt(msg);
// Compute homomorphically a negation
sks.unchecked_neg_assign(&mut ctxt);
// Decrypt
let dec: u64 = cks.decrypt(&ctxt);
assert_eq!(modulus - msg, dec);
Sourcepub fn unchecked_neg_assign<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
pub fn unchecked_neg_assign<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the input ciphertext.
Sourcepub fn is_neg_possible<T>(&self, ctxt: &T) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn is_neg_possible<T>(&self, ctxt: &T) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Verifies if ct can be negated.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 2u64;
// Encrypt a message
let ctxt = cks.encrypt(msg);
// Check if we can perform a negation
sks.is_neg_possible(&ctxt).unwrap();
Sourcepub fn checked_neg<T>(&self, ctxt: &T) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_neg<T>(&self, ctxt: &T) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
// Encrypt a message
let ctxt = cks.encrypt(msg);
// Compute homomorphically a negation:
let ct_res = sks.checked_neg(&ctxt);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(255, clear);
}
}
Sourcepub fn checked_neg_assign<T>(&self, ctxt: &mut T) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_neg_assign<T>(&self, ctxt: &mut T) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let modulus = 1 << 8;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1;
// Encrypt a message
let mut ct = cks.encrypt(msg);
// Compute homomorphically a negation:
sks.checked_neg_assign(&mut ct).unwrap();
let clear_res: u64 = cks.decrypt(&ct);
assert_eq!(clear_res, (modulus - msg));
Sourcepub fn smart_neg<T>(&self, ctxt: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_neg<T>(&self, ctxt: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
// Encrypt two messages:
let mut ctxt = cks.encrypt(msg);
// Compute homomorphically a negation
let ct_res = sks.smart_neg(&mut ctxt);
// Decrypt
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(255, dec);
Sourcepub fn smart_neg_assign<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
pub fn smart_neg_assign<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
The result is assigned to the input ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
// Encrypt two messages:
let mut ctxt = cks.encrypt(msg);
// Compute homomorphically a negation
sks.smart_neg_assign(&mut ctxt);
// Decrypt
let dec: u64 = cks.decrypt(&ctxt);
assert_eq!(255, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_scalar_add<T, C>(&self, ct: &C, scalar: T) -> C
pub fn unchecked_scalar_add<T, C>(&self, ct: &C, scalar: T) -> C
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 4;
let scalar = 40;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.unchecked_scalar_add(&ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + scalar, dec);
Sourcepub fn unchecked_scalar_add_assign<T, C>(&self, ct: &mut C, scalar: T)
pub fn unchecked_scalar_add_assign<T, C>(&self, ct: &mut C, scalar: T)
Computes homomorphically an addition between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
Sourcepub fn is_scalar_add_possible<T, C>(
&self,
ct: &C,
scalar: T,
) -> Result<(), CheckError>
pub fn is_scalar_add_possible<T, C>( &self, ct: &C, scalar: T, ) -> Result<(), CheckError>
Verifies if a scalar can be added to a ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 2u64;
let scalar = 40;
// Encrypt two messages:
let ct1 = cks.encrypt(msg);
// Check if we can perform an addition
sks.is_scalar_add_possible(&ct1, scalar).unwrap();
Sourcepub fn checked_scalar_add<T, C>(
&self,
ct: &C,
scalar: T,
) -> Result<C, CheckError>
pub fn checked_scalar_add<T, C>( &self, ct: &C, scalar: T, ) -> Result<C, CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 4;
let scalar = 40;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.checked_scalar_add(&ct, scalar).unwrap();
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + scalar, dec);
Sourcepub fn checked_scalar_add_assign<T, C>(
&self,
ct: &mut C,
scalar: T,
) -> Result<(), CheckError>
pub fn checked_scalar_add_assign<T, C>( &self, ct: &mut C, scalar: T, ) -> Result<(), CheckError>
Computes homomorphically an addition between a scalar and a ciphertext.
If the operation can be performed, the result is stored in the ct_left
ciphertext.
Otherwise a CheckError is returned, and ct_left
is not modified.
Sourcepub fn smart_scalar_add<T, C>(&self, ct: &mut C, scalar: T) -> C
pub fn smart_scalar_add<T, C>(&self, ct: &mut C, scalar: T) -> C
Computes homomorphically the addition of ciphertext with a scalar.
The result is returned in a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 4;
let scalar = 40;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.smart_scalar_add(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + scalar, dec);
Sourcepub fn smart_scalar_add_assign<T, C>(&self, ct: &mut C, scalar: T)
pub fn smart_scalar_add_assign<T, C>(&self, ct: &mut C, scalar: T)
Computes homomorphically the addition of ciphertext with a scalar.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 129;
let scalar = 40;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
sks.smart_scalar_add_assign(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg + scalar, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_small_scalar_mul(
&self,
ctxt: &RadixCiphertext,
scalar: u64,
) -> RadixCiphertext
pub fn unchecked_small_scalar_mul( &self, ctxt: &RadixCiphertext, scalar: u64, ) -> RadixCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 30;
let scalar = 3;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.unchecked_small_scalar_mul(&ct, scalar);
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(scalar * msg, clear);
pub fn unchecked_small_scalar_mul_assign( &self, ctxt: &mut RadixCiphertext, scalar: u64, )
Sourcepub fn is_small_scalar_mul_possible(
&self,
ctxt: &RadixCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn is_small_scalar_mul_possible( &self, ctxt: &RadixCiphertext, scalar: u64, ) -> Result<(), CheckError>
Verifies if ct1 can be multiplied by scalar.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 25u64;
let scalar1 = 3;
let ct = cks.encrypt(msg);
// Verification if the scalar multiplication can be computed:
sks.is_small_scalar_mul_possible(&ct, scalar1).unwrap();
let scalar2 = 7;
// Verification if the scalar multiplication can be computed:
let res = sks.is_small_scalar_mul_possible(&ct, scalar2);
assert!(res.is_err());
Sourcepub fn checked_small_scalar_mul(
&self,
ct: &RadixCiphertext,
scalar: u64,
) -> Result<RadixCiphertext, CheckError>
pub fn checked_small_scalar_mul( &self, ct: &RadixCiphertext, scalar: u64, ) -> Result<RadixCiphertext, CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 33;
let scalar = 3;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.checked_small_scalar_mul(&ct, scalar);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(msg * scalar, clear);
}
}
Sourcepub fn checked_small_scalar_mul_assign(
&self,
ct: &mut RadixCiphertext,
scalar: u64,
) -> Result<(), CheckError>
pub fn checked_small_scalar_mul_assign( &self, ct: &mut RadixCiphertext, scalar: u64, ) -> Result<(), CheckError>
Computes homomorphically a multiplication between a scalar and a ciphertext.
If the operation can be performed, the result is assigned to the ciphertext given as parameter. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 33;
let scalar = 3;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
sks.checked_small_scalar_mul_assign(&mut ct, scalar)
.unwrap();
let clear_res: u64 = cks.decrypt(&ct);
assert_eq!(clear_res, msg * scalar);
Sourcepub fn smart_small_scalar_mul(
&self,
ctxt: &mut RadixCiphertext,
scalar: u64,
) -> RadixCiphertext
pub fn smart_small_scalar_mul( &self, ctxt: &mut RadixCiphertext, scalar: u64, ) -> RadixCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar value shall fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let modulus = 1 << 8;
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 13;
let scalar = 2;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_small_scalar_mul(&mut ct, scalar);
// Decrypt:
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(msg * scalar % modulus, clear);
Sourcepub fn smart_small_scalar_mul_assign(
&self,
ctxt: &mut RadixCiphertext,
scalar: u64,
)
pub fn smart_small_scalar_mul_assign( &self, ctxt: &mut RadixCiphertext, scalar: u64, )
Computes homomorphically a multiplication between a scalar and a ciphertext.
small
means the scalar shall value fit in a shortint block.
For example, if the parameters are PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
the scalar should fit in 2 bits.
The result is assigned to the input ciphertext
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let modulus = 1 << 8;
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 9;
let scalar = 3;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
sks.smart_small_scalar_mul_assign(&mut ct, scalar);
// Decrypt:
let clear: u64 = cks.decrypt(&ct);
assert_eq!(msg * scalar % modulus, clear);
Sourcepub fn blockshift<T>(&self, ctxt: &T, shift: usize) -> Twhere
T: IntegerRadixCiphertext,
pub fn blockshift<T>(&self, ctxt: &T, shift: usize) -> Twhere
T: IntegerRadixCiphertext,
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
let power = 2;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.blockshift(&ct, power);
// Decrypt:
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(16, clear);
Sourcepub fn smart_scalar_mul<T>(
&self,
ctxt: &mut RadixCiphertext,
scalar: T,
) -> RadixCiphertext
pub fn smart_scalar_mul<T>( &self, ctxt: &mut RadixCiphertext, scalar: T, ) -> RadixCiphertext
Computes homomorphically a multiplication between a scalar and a ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let modulus = 1 << 8;
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 230;
let scalar = 376;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_scalar_mul(&mut ct, scalar);
// Decrypt:
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(msg * scalar % modulus, clear);
pub fn smart_scalar_mul_assign<T>(&self, ctxt: &mut RadixCiphertext, scalar: T)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_scalar_sub<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
pub fn unchecked_scalar_sub<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
Computes homomorphically a subtraction between a ciphertext and a scalar.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 40;
let scalar = 3;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.unchecked_scalar_sub(&ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg - scalar, dec);
pub fn unchecked_scalar_sub_assign<T, Scalar>(&self, ct: &mut T, scalar: Scalar)
Sourcepub fn is_scalar_sub_possible<T, Scalar>(
&self,
ct: &T,
scalar: Scalar,
) -> Result<(), CheckError>
pub fn is_scalar_sub_possible<T, Scalar>( &self, ct: &T, scalar: Scalar, ) -> Result<(), CheckError>
Verifies if the subtraction of a ciphertext by scalar can be computed.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 40u64;
let scalar = 2u64;
let ct1 = cks.encrypt(msg);
// Check if we can perform an addition
sks.is_scalar_sub_possible(&ct1, scalar).unwrap();
Sourcepub fn checked_scalar_sub<T, Scalar>(
&self,
ct: &T,
scalar: Scalar,
) -> Result<T, CheckError>
pub fn checked_scalar_sub<T, Scalar>( &self, ct: &T, scalar: Scalar, ) -> Result<T, CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 40;
let scalar = 4;
let ct = cks.encrypt(msg);
// Compute the subtraction:
let ct_res = sks.checked_scalar_sub(&ct, scalar).unwrap();
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg - scalar, dec);
Sourcepub fn checked_scalar_sub_assign<T, Scalar>(
&self,
ct: &mut T,
scalar: Scalar,
) -> Result<(), CheckError>
pub fn checked_scalar_sub_assign<T, Scalar>( &self, ct: &mut T, scalar: Scalar, ) -> Result<(), CheckError>
Computes homomorphically a subtraction of a ciphertext by a scalar.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 232;
let scalar = 83;
let mut ct = cks.encrypt(msg);
// Compute the subtraction:
sks.checked_scalar_sub_assign(&mut ct, scalar).unwrap();
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg - scalar, dec);
Sourcepub fn smart_scalar_sub<T, Scalar>(&self, ct: &mut T, scalar: Scalar) -> T
pub fn smart_scalar_sub<T, Scalar>(&self, ct: &mut T, scalar: Scalar) -> T
Computes homomorphically a subtraction of a ciphertext by a scalar.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 165;
let scalar = 112;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.smart_scalar_sub(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg - scalar, dec);
pub fn smart_scalar_sub_assign<T, Scalar>( &self, ct: &mut RadixCiphertext, scalar: Scalar, )
Source§impl ServerKey
impl ServerKey
Sourcepub fn blockshift_right(
&self,
ctxt: &RadixCiphertext,
shift: usize,
) -> RadixCiphertext
pub fn blockshift_right( &self, ctxt: &RadixCiphertext, shift: usize, ) -> RadixCiphertext
Shifts the blocks to the right.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 16;
let shift = 2;
// Encrypt two messages:
let ct = cks.encrypt(msg);
let ct_res = sks.blockshift_right(&ct, shift);
let div = cks.parameters().message_modulus().0.pow(shift as u32);
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!(msg / div, clear);
pub fn blockshift_right_assign(&self, ctxt: &mut RadixCiphertext, shift: usize)
Sourcepub fn unchecked_scalar_right_shift<T>(
&self,
ct: &RadixCiphertext,
shift: T,
) -> RadixCiphertext
pub fn unchecked_scalar_right_shift<T>( &self, ct: &RadixCiphertext, shift: T, ) -> RadixCiphertext
Computes homomorphically a right shift.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 128u64;
let shift = 2;
let ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
let ct_res = sks.unchecked_scalar_right_shift(&ct, shift);
// Decrypt:
let dec = cks.decrypt(&ct_res);
assert_eq!(msg >> shift, dec);
Sourcepub fn unchecked_scalar_right_shift_assign<T>(
&self,
ct: &mut RadixCiphertext,
shift: T,
)
pub fn unchecked_scalar_right_shift_assign<T>( &self, ct: &mut RadixCiphertext, shift: T, )
Computes homomorphically a right shift.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 18u64;
let shift = 4;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
sks.unchecked_scalar_right_shift_assign(&mut ct, shift);
// Decrypt:
let dec = cks.decrypt(&ct);
assert_eq!(msg >> shift, dec);
Sourcepub fn unchecked_scalar_left_shift<T>(
&self,
ct_left: &RadixCiphertext,
shift: T,
) -> RadixCiphertext
pub fn unchecked_scalar_left_shift<T>( &self, ct_left: &RadixCiphertext, shift: T, ) -> RadixCiphertext
Computes homomorphically a left shift by a scalar.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 21u64;
let shift = 2;
let ct1 = cks.encrypt(msg);
// Compute homomorphically a left shift:
let ct_res = sks.unchecked_scalar_left_shift(&ct1, shift);
// Decrypt:
let dec = cks.decrypt(&ct_res);
assert_eq!(msg << shift, dec);
Sourcepub fn unchecked_scalar_left_shift_assign<T>(
&self,
ct: &mut RadixCiphertext,
shift: T,
)
pub fn unchecked_scalar_left_shift_assign<T>( &self, ct: &mut RadixCiphertext, shift: T, )
Computes homomorphically a left shift by a scalar.
The result is assigned in the input ciphertext
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The ct carry buffers will be clean / empty afterwards
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 13u64;
let shift = 2;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
sks.unchecked_scalar_left_shift_assign(&mut ct, shift);
// Decrypt:
let dec = cks.decrypt(&ct);
assert_eq!(msg << shift, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn scalar_blockslice<B, R>(
&self,
ctxt: &RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn scalar_blockslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of blocks from a ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_block = 1;
let end_block = 2;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks.scalar_blockslice(&ct, start_block..end_block).unwrap();
let blocksize = cks.parameters().message_modulus().0.ilog2() as u64;
let start_bit = (start_block as u64) * blocksize;
let end_bit = (end_block as u64) * blocksize;
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn scalar_blockslice_assign(
&self,
ctxt: &mut RadixCiphertext,
start_block: usize,
end_block: usize,
)
pub fn scalar_blockslice_assign( &self, ctxt: &mut RadixCiphertext, start_block: usize, end_block: usize, )
Extract a slice of blocks from a ciphertext.
The result is assigned in the input ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_block = 1;
let end_block = 2;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.scalar_blockslice_assign(&mut ct, start_block, end_block);
let blocksize = cks.parameters().message_modulus().0.ilog2() as u64;
let start_bit = (start_block as u64) * blocksize;
let end_bit = (end_block as u64) * blocksize;
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn unchecked_scalar_bitslice<B, R>(
&self,
ctxt: &RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn unchecked_scalar_bitslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks
.unchecked_scalar_bitslice(&ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn unchecked_scalar_bitslice_assign<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn unchecked_scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.unchecked_scalar_bitslice_assign(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn scalar_bitslice<B, R>(
&self,
ctxt: &RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn scalar_bitslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks.scalar_bitslice(&ct, start_bit..end_bit).unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn scalar_bitslice_assign<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks.scalar_bitslice(&ct, start_bit..end_bit).unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn smart_scalar_bitslice<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn smart_scalar_bitslice<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
let ct_res = sks
.smart_scalar_bitslice(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn smart_scalar_bitslice_assign<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn smart_scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.smart_scalar_bitslice_assign(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_sub<T>(&self, ctxt_left: &T, ctxt_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_sub<T>(&self, ctxt_left: &T, ctxt_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 12;
let msg_2 = 10;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg_1);
let ctxt_2 = cks.encrypt(msg_2);
// Compute homomorphically a subtraction:
let ct_res = sks.unchecked_sub(&ctxt_1, &ctxt_2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg_1 - msg_2);
Sourcepub fn unchecked_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &T)where
T: IntegerRadixCiphertext,
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 128;
let msg_2 = 99;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1);
let ctxt_2 = cks.encrypt(msg_2);
// Compute homomorphically a subtraction:
sks.unchecked_sub_assign(&mut ctxt_1, &ctxt_2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ctxt_1);
assert_eq!(dec_result, msg_1 - msg_2);
Sourcepub fn is_sub_possible<T>(
&self,
ctxt_left: &T,
ctxt_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn is_sub_possible<T>(
&self,
ctxt_left: &T,
ctxt_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Verifies if ct_right can be subtracted to ct_left.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 182u64;
let msg_2 = 120u64;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg_1);
let ctxt_2 = cks.encrypt(msg_2);
// Check if we can perform a subtraction
sks.is_sub_possible(&ctxt_1, &ctxt_2).unwrap();
Sourcepub fn checked_sub<T>(
&self,
ctxt_left: &T,
ctxt_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_sub<T>(
&self,
ctxt_left: &T,
ctxt_right: &T,
) -> Result<T, CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 1u64;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg);
let ctxt_2 = cks.encrypt(msg);
// Compute homomorphically a subtraction:
let ct_res = sks.checked_sub(&ctxt_1, &ctxt_2);
match ct_res {
Err(x) => panic!("{x:?}"),
Ok(y) => {
let clear: u64 = cks.decrypt(&y);
assert_eq!(0, clear);
}
}
Sourcepub fn checked_sub_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
pub fn checked_sub_assign<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> Result<(), CheckError>where
T: IntegerRadixCiphertext,
Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
If the operation can be performed, the result is returned in a new ciphertext. Otherwise a CheckError is returned.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 41u8;
let msg2 = 101u8;
let mut ct1 = cks.encrypt(msg1 as u64);
let ct2 = cks.encrypt(msg2 as u64);
// Compute homomorphically an addition:
sks.checked_sub_assign(&mut ct1, &ct2).unwrap();
let clear: u64 = cks.decrypt(&ct1);
assert_eq!(msg1.wrapping_sub(msg2) as u64, clear);
Sourcepub fn smart_sub<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_sub<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1 as u64);
let mut ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
let ct_res = sks.smart_sub(&mut ctxt_1, &mut ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn smart_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T)where
T: IntegerRadixCiphertext,
pub fn smart_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T)where
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1 as u64);
let mut ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
sks.smart_sub_assign(&mut ctxt_1, &mut ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ctxt_1);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn unsigned_overflowing_sub(
&self,
ctxt_left: &RadixCiphertext,
ctxt_right: &RadixCiphertext,
) -> (RadixCiphertext, BooleanBlock)
pub fn unsigned_overflowing_sub( &self, ctxt_left: &RadixCiphertext, ctxt_right: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
Computes the subtraction and returns an indicator of overflow
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 1u8;
let msg_2 = 2u8;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg_1);
let ctxt_2 = cks.encrypt(msg_2);
// Compute homomorphically a subtraction
let (result, overflowed) = sks.unsigned_overflowing_sub(&ctxt_1, &ctxt_2);
// Decrypt:
let decrypted_result: u8 = cks.decrypt(&result);
let decrypted_overflow = cks.decrypt_bool(&overflowed);
let (expected_result, expected_overflow) = msg_1.overflowing_sub(msg_2);
assert_eq!(expected_result, decrypted_result);
assert_eq!(expected_overflow, decrypted_overflow);
pub fn unchecked_unsigned_overflowing_sub( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_signed_overflowing_sub( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
pub fn signed_overflowing_sub( &self, ctxt_left: &SignedRadixCiphertext, ctxt_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_is_even<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_is_even<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is even
ct is not required to have clean carries
Sourcepub fn unchecked_is_odd<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_is_odd<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is odd ct is not required to have clean carries
Sourcepub fn smart_is_even_parallelized<T>(&self, ct: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_is_even_parallelized<T>(&self, ct: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is even
Sourcepub fn smart_is_odd_parallelized<T>(&self, ct: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_is_odd_parallelized<T>(&self, ct: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is odd
Sourcepub fn is_even_parallelized<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn is_even_parallelized<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is even
Sourcepub fn is_odd_parallelized<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn is_odd_parallelized<T>(&self, ct: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encryption of true if the value is odd
Source§impl ServerKey
impl ServerKey
pub fn create_trivial_zero_assign_radix<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
Sourcepub fn create_trivial_zero_radix<T>(&self, num_blocks: usize) -> Twhere
T: IntegerRadixCiphertext,
pub fn create_trivial_zero_radix<T>(&self, num_blocks: usize) -> Twhere
T: IntegerRadixCiphertext,
Create a ciphertext filled with zeros
§Example
use tfhe::integer::{gen_keys_radix, RadixCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let ctxt: RadixCiphertext = sks.create_trivial_zero_radix(num_blocks);
// Decrypt:
let dec: u64 = cks.decrypt(&ctxt);
assert_eq!(0, dec);
pub fn create_trivial_boolean_block(&self, value: bool) -> BooleanBlock
pub fn create_trivial_max_radix<T>(&self, num_blocks: usize) -> Twhere
T: IntegerRadixCiphertext,
pub fn create_trivial_min_radix<T>(&self, num_blocks: usize) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn create_trivial_radix<T, C>(&self, value: T, num_blocks: usize) -> C
pub fn create_trivial_radix<T, C>(&self, value: T, num_blocks: usize) -> C
Create a trivial radix ciphertext
Trivial means that the value is not encrypted
§Example
use tfhe::integer::{gen_keys_radix, RadixCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let ctxt: RadixCiphertext = sks.create_trivial_radix(212u64, num_blocks);
// Decrypt:
let dec: u64 = cks.decrypt(&ctxt);
assert_eq!(212, dec);
Sourcepub fn extend_radix_with_trivial_zero_blocks_lsb_assign(
&self,
ct: &mut RadixCiphertext,
num_blocks: usize,
)
pub fn extend_radix_with_trivial_zero_blocks_lsb_assign( &self, ct: &mut RadixCiphertext, num_blocks: usize, )
Prepend trivial zero LSB blocks to an existing RadixCiphertext
. This can be useful for
casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let mut ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
let added_blocks = 2;
sks.extend_radix_with_trivial_zero_blocks_lsb_assign(&mut ct1, added_blocks);
assert_eq!(ct1.blocks().len(), 6);
// Decrypt
let res: u64 = cks.decrypt(&ct1);
assert_eq!(
7 * (PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128
.message_modulus
.0)
.pow(added_blocks as u32),
res
);
Sourcepub fn extend_radix_with_trivial_zero_blocks_lsb(
&self,
ct: &RadixCiphertext,
num_blocks: usize,
) -> RadixCiphertext
pub fn extend_radix_with_trivial_zero_blocks_lsb( &self, ct: &RadixCiphertext, num_blocks: usize, ) -> RadixCiphertext
Prepend trivial zero LSB blocks to an existing RadixCiphertext
and returns the result as
a new RadixCiphertext
. This can be useful for casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
let added_blocks = 2;
let ct_res = sks.extend_radix_with_trivial_zero_blocks_lsb(&ct1, added_blocks);
assert_eq!(ct_res.blocks().len(), 6);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(
7 * (PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128
.message_modulus
.0)
.pow(added_blocks as u32),
res
);
Sourcepub fn extend_radix_with_trivial_zero_blocks_msb_assign(
&self,
ct: &mut RadixCiphertext,
num_blocks: usize,
)
pub fn extend_radix_with_trivial_zero_blocks_msb_assign( &self, ct: &mut RadixCiphertext, num_blocks: usize, )
Append trivial zero MSB blocks to an existing RadixCiphertext
. This can be useful for
casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let mut ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
sks.extend_radix_with_trivial_zero_blocks_msb_assign(&mut ct1, 2);
assert_eq!(ct1.blocks().len(), 6);
// Decrypt
let res: u64 = cks.decrypt(&ct1);
assert_eq!(7, res);
Sourcepub fn extend_radix_with_trivial_zero_blocks_msb(
&self,
ct: &RadixCiphertext,
num_blocks: usize,
) -> RadixCiphertext
pub fn extend_radix_with_trivial_zero_blocks_msb( &self, ct: &RadixCiphertext, num_blocks: usize, ) -> RadixCiphertext
Append trivial zero MSB blocks to an existing RadixCiphertext
and returns the result as
a new RadixCiphertext
. This can be useful for casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
let ct_res = sks.extend_radix_with_trivial_zero_blocks_msb(&ct1, 2);
assert_eq!(ct_res.blocks().len(), 6);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(7, res);
Sourcepub fn trim_radix_blocks_lsb_assign(
&self,
ct: &mut RadixCiphertext,
num_blocks: usize,
)
pub fn trim_radix_blocks_lsb_assign( &self, ct: &mut RadixCiphertext, num_blocks: usize, )
Remove LSB blocks from an existing RadixCiphertext
. This can be useful for casting
operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 119u64;
let mut ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
sks.trim_radix_blocks_lsb_assign(&mut ct1, 2);
assert_eq!(ct1.blocks().len(), 2);
// Decrypt
let res: u64 = cks.decrypt(&ct1);
assert_eq!(7, res);
Sourcepub fn trim_radix_blocks_lsb(
&self,
ct: &RadixCiphertext,
num_blocks: usize,
) -> RadixCiphertext
pub fn trim_radix_blocks_lsb( &self, ct: &RadixCiphertext, num_blocks: usize, ) -> RadixCiphertext
Remove LSB blocks from an existing RadixCiphertext
and returns the result as a new
RadixCiphertext
. This can be useful for casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 119u64;
let ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
let ct_res = sks.trim_radix_blocks_lsb(&ct1, 2);
assert_eq!(ct_res.blocks().len(), 2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(7, res);
Sourcepub fn trim_radix_blocks_msb_assign(
&self,
ct: &mut RadixCiphertext,
num_blocks: usize,
)
pub fn trim_radix_blocks_msb_assign( &self, ct: &mut RadixCiphertext, num_blocks: usize, )
Remove MSB blocks from an existing RadixCiphertext
. This can be useful for
casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 119u64;
let mut ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
sks.trim_radix_blocks_msb_assign(&mut ct1, 2);
assert_eq!(ct1.blocks().len(), 2);
// Decrypt
let res: u64 = cks.decrypt(&ct1);
assert_eq!(7, res);
Sourcepub fn trim_radix_blocks_msb(
&self,
ct: &RadixCiphertext,
num_blocks: usize,
) -> RadixCiphertext
pub fn trim_radix_blocks_msb( &self, ct: &RadixCiphertext, num_blocks: usize, ) -> RadixCiphertext
Remove MSB blocks from an existing RadixCiphertext
and returns the result as a new
RadixCiphertext
. This can be useful for casting operations.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 119u64;
let ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), 4);
let ct_res = sks.trim_radix_blocks_msb(&ct1, 2);
assert_eq!(ct_res.blocks().len(), 2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(7, res);
Sourcepub fn extend_radix_with_sign_msb_assign(
&self,
ct: &mut SignedRadixCiphertext,
num_blocks: usize,
)
pub fn extend_radix_with_sign_msb_assign( &self, ct: &mut SignedRadixCiphertext, num_blocks: usize, )
Extends the most significant blocks using the sign bit. Used to cast SignedRadixCiphertext
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = -1i8;
let mut ct1 = cks.encrypt_signed(msg);
assert_eq!(ct1.blocks().len(), 4);
sks.extend_radix_with_sign_msb_assign(&mut ct1, 4);
assert_eq!(ct1.blocks().len(), 8);
// Decrypt
let res: i16 = cks.decrypt_signed(&ct1);
assert_eq!(-1, res);
Sourcepub fn extend_radix_with_sign_msb(
&self,
ct: &SignedRadixCiphertext,
num_blocks: usize,
) -> SignedRadixCiphertext
pub fn extend_radix_with_sign_msb( &self, ct: &SignedRadixCiphertext, num_blocks: usize, ) -> SignedRadixCiphertext
Extends the most significant blocks using the sign bit. Used to cast SignedRadixCiphertext
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = -2i8;
let ct1 = cks.encrypt_signed(msg);
assert_eq!(ct1.blocks().len(), 4);
let ct_res = sks.extend_radix_with_sign_msb(&ct1, 4);
assert_eq!(ct_res.blocks().len(), 8);
// Decrypt
let res: i16 = cks.decrypt_signed(&ct_res);
assert_eq!(-2, res);
Sourcepub fn cast_to_unsigned<T: IntegerRadixCiphertext>(
&self,
source: T,
target_num_blocks: usize,
) -> RadixCiphertext
pub fn cast_to_unsigned<T: IntegerRadixCiphertext>( &self, source: T, target_num_blocks: usize, ) -> RadixCiphertext
Cast a RadixCiphertext or SignedRadixCiphertext to a RadixCiphertext with a possibly different number of blocks
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = -2i8;
let ct1 = cks.encrypt_signed(msg);
assert_eq!(ct1.blocks().len(), 4);
let ct_res = sks.cast_to_unsigned(ct1, 8);
assert_eq!(ct_res.blocks().len(), 8);
// Decrypt
let res: u16 = cks.decrypt(&ct_res);
assert_eq!(msg as u16, res);
Sourcepub fn cast_to_signed<T: IntegerRadixCiphertext>(
&self,
source: T,
target_num_blocks: usize,
) -> SignedRadixCiphertext
pub fn cast_to_signed<T: IntegerRadixCiphertext>( &self, source: T, target_num_blocks: usize, ) -> SignedRadixCiphertext
Cast a RadixCiphertext or SignedRadixCiphertext to a SignedRadixCiphertext with a possibly different number of blocks
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 8;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = u16::MAX;
let ct1 = cks.encrypt(msg);
assert_eq!(ct1.blocks().len(), num_blocks);
let ct_res = sks.cast_to_signed(ct1, 4);
assert_eq!(ct_res.blocks().len(), 4);
// Decrypt
let res: i8 = cks.decrypt_signed(&ct_res);
assert_eq!(msg as i8, res);
Sourcepub fn propagate<T>(&self, ctxt: &mut T, index: usize)where
T: IntegerRadixCiphertext,
pub fn propagate<T>(&self, ctxt: &mut T, index: usize)where
T: IntegerRadixCiphertext,
Propagate the carry of the ‘index’ block to the next one.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);
// Compute homomorphically an addition:
let mut ct_res = sks.unchecked_add(&ct1, &ct2);
sks.propagate(&mut ct_res, 0);
// Decrypt one block:
let res: u64 = cks.decrypt_one_block(&ct_res.blocks()[1]);
assert_eq!(3, res);
Sourcepub fn full_propagate<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
pub fn full_propagate<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
Propagate all the carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 10;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);
// Compute homomorphically an addition:
let mut ct_res = sks.unchecked_add(&ct1, &ct2);
sks.full_propagate(&mut ct_res);
// Decrypt:
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + msg, res);
Source§impl ServerKey
impl ServerKey
pub fn unchecked_abs_parallelized<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_abs_parallelized<T>(&self, ct: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn abs_parallelized<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
Source§impl ServerKey
impl ServerKey
pub fn unchecked_add_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_add_assign_parallelized<T>(&self, lhs: &mut T, rhs: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn smart_add_parallelized<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_add_parallelized<T>(&self, ct_left: &mut T, ct_right: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.smart_add_parallelized(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 + msg2);
pub fn smart_add_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn add_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn add_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically an addition between two ciphertexts encrypting integer values.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically an addition:
let ct_res = sks.add_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 + msg2);
pub fn add_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn overflowing_add_parallelized<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn overflowing_add_parallelized<T>(
&self,
ct_left: &T,
ct_right: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
Computes the addition of two ciphertexts and returns the overflow flag
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = u8::MAX;
let msg2 = 1;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let (ct_res, overflowed) = sks.unsigned_overflowing_add_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct_res);
let dec_overflowed = cks.decrypt_bool(&overflowed);
let (expected_result, expected_overflow) = msg1.overflowing_add(msg2);
assert_eq!(dec_result, expected_result);
assert_eq!(dec_overflowed, expected_overflow);
pub fn overflowing_add_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &T,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Sourcepub fn unsigned_overflowing_add_parallelized(
&self,
ct_left: &RadixCiphertext,
ct_right: &RadixCiphertext,
) -> (RadixCiphertext, BooleanBlock)
pub fn unsigned_overflowing_add_parallelized( &self, ct_left: &RadixCiphertext, ct_right: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
Computes the addition of two unsigned ciphertexts and returns the overflow flag
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = u8::MAX;
let msg2 = 1;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let (ct_res, overflowed) = sks.unsigned_overflowing_add_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct_res);
let dec_overflowed = cks.decrypt_bool(&overflowed);
let (expected_result, expected_overflow) = msg1.overflowing_add(msg2);
assert_eq!(dec_result, expected_result);
assert_eq!(dec_overflowed, expected_overflow);
pub fn unsigned_overflowing_add_assign_parallelized( &self, ct_left: &mut RadixCiphertext, ct_right: &RadixCiphertext, ) -> BooleanBlock
pub fn signed_overflowing_add_parallelized( &self, ct_left: &SignedRadixCiphertext, ct_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
pub fn unchecked_signed_overflowing_add_parallelized( &self, ct_left: &SignedRadixCiphertext, ct_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Sourcepub fn add_assign_with_carry_parallelized<T>(
&self,
lhs: &mut T,
rhs: &T,
input_carry: Option<&BooleanBlock>,
)where
T: IntegerRadixCiphertext,
pub fn add_assign_with_carry_parallelized<T>(
&self,
lhs: &mut T,
rhs: &T,
input_carry: Option<&BooleanBlock>,
)where
T: IntegerRadixCiphertext,
Does lhs += (rhs + carry)
Sourcepub fn overflowing_add_assign_with_carry<T>(
&self,
lhs: &mut T,
rhs: &T,
input_carry: Option<&BooleanBlock>,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn overflowing_add_assign_with_carry<T>(
&self,
lhs: &mut T,
rhs: &T,
input_carry: Option<&BooleanBlock>,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Does lhs += (rhs + carry)
Returns a boolean block that encrypts true
if overflow happened
Source§impl ServerKey
impl ServerKey
pub fn unchecked_bitand_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitand_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn smart_bitand_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitand_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitand_parallelized(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 & msg2);
pub fn smart_bitand_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn bitand_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn bitand_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitand between two ciphertexts encrypting integer values.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.bitand_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 & msg2);
pub fn bitand_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_bitor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitor_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn smart_bitor_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitor_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitor between two ciphertexts encrypting integer values.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 | msg2);
pub fn smart_bitor_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn bitor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn bitor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitor between two ciphertexts encrypting integer values.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.bitor_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 | msg2);
pub fn bitor_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_bitxor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_bitxor_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn smart_bitxor_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_bitxor_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let mut ct1 = cks.encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);
let ct_res = sks.smart_bitxor_parallelized(&mut ct1, &mut ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 ^ msg2);
pub fn smart_bitxor_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &mut T,
)where
T: IntegerRadixCiphertext,
Sourcepub fn bitxor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn bitxor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14;
let msg2 = 97;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
let ct_res = sks.bitxor_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 ^ msg2);
pub fn bitxor_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn bitnot<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn bitnot<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a bitnot on a ciphertext encrypting integer values.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertext block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 14;
let ct = cks.encrypt(msg);
let ct_res = sks.bitnot(&ct);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, (!msg) % (1 << 8));
pub fn bitnot_assign<T>(&self, ct: &mut T)where
T: IntegerRadixCiphertext,
Source§impl ServerKey
impl ServerKey
pub fn unchecked_block_rotate_right<T>(
&self,
ct: &T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_block_rotate_left<T>(
&self,
ct: &T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_block_shift_right<T>(
&self,
ct: &T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_block_shift_left<T>(
&self,
ct: &T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_block_shift_left<T>(
&self,
ct: &T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
shift blocks to the left
Note that as shifting blocks to the left is equivalent to shifting bits to the right this will perform an ‘arithmetic’ shift when left shifting a SignedRadixInteger If this is not the wanted behaviour, you can first cast the input to unsigned radix
pub fn smart_block_rotate_right<T>(
&self,
ct: &mut T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_block_rotate_left<T>(
&self,
ct: &mut T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_block_shift_right<T>(
&self,
ct: &mut T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_block_shift_left<T>(
&self,
ct: &mut T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_block_shift_left<T>(
&self,
ct: &mut T,
amount: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
shift blocks to the left
Note that as shifting blocks to the left is equivalent to shifting bits to the right this will perform an ‘arithmetic’ shift when left shifting a SignedRadixInteger If this is not the wanted behaviour, you can first cast the input to unsigned radix
pub fn block_rotate_right<T>(&self, ct: &T, amount: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn block_rotate_left<T>(&self, ct: &T, amount: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn block_shift_right<T>(&self, ct: &T, amount: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn block_shift_left<T>(&self, ct: &T, amount: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn block_shift_left<T>(&self, ct: &T, amount: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
shift blocks to the left
Note that as shifting blocks to the left is equivalent to shifting bits to the right this will perform an ‘arithmetic’ shift when left shifting a SignedRadixInteger If this is not the wanted behaviour, you can first cast the input to unsigned radix
Source§impl ServerKey
impl ServerKey
pub fn unchecked_if_then_else_parallelized<T>(
&self,
condition: &BooleanBlock,
true_ct: &T,
false_ct: &T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn scalar_cmux_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T
pub fn scalar_select_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T
pub fn scalar_if_then_else_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T
pub fn unchecked_cmux<T>(
&self,
condition: &BooleanBlock,
true_ct: &T,
false_ct: &T,
) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn cmux_parallelized<T>(
&self,
condition: &BooleanBlock,
true_ct: &T,
false_ct: &T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn cmux_parallelized<T>(
&self,
condition: &BooleanBlock,
true_ct: &T,
false_ct: &T,
) -> Twhere
T: IntegerRadixCiphertext,
Encrypted CMUX.
It is another name for Self::if_then_else_parallelized
Sourcepub fn smart_if_then_else_parallelized<T>(
&self,
condition: &mut BooleanBlock,
true_ct: &mut T,
false_ct: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_if_then_else_parallelized<T>(
&self,
condition: &mut BooleanBlock,
true_ct: &mut T,
false_ct: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_ct or false_ct depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_ct.
- If condition == 0, the returned ciphertext will encrypt the same value as false_ct.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as either true_ct or false_ct, it won’t exactly be true_ct or false_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let a = 128u8;
let b = 55u8;
let mut ct_a = cks.encrypt(a);
let mut ct_b = cks.encrypt(b);
let mut condition = sks.scalar_ge_parallelized(&ct_a, 66);
let ct_res = sks.smart_if_then_else_parallelized(&mut condition, &mut ct_a, &mut ct_b);
// Decrypt:
let dec: u8 = cks.decrypt(&ct_res);
assert_eq!(if a >= 66 { a } else { b }, dec);
assert_ne!(ct_a, ct_res);
assert_ne!(ct_b, ct_res);
Sourcepub fn smart_cmux_parallelized<T>(
&self,
condition: &mut BooleanBlock,
true_ct: &mut T,
false_ct: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_cmux_parallelized<T>(
&self,
condition: &mut BooleanBlock,
true_ct: &mut T,
false_ct: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
Encrypted CMUX.
It is another name for Self::smart_if_then_else_parallelized
Source§impl ServerKey
impl ServerKey
pub fn unchecked_eq_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_ne_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_gt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_ge_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_lt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_le_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_max_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_min_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_eq_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_ne_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_gt_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_ge_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_lt_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_le_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_max_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_min_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn eq_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn ne_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn gt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn ge_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn lt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn le_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn max_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn min_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
Source§impl ServerKey
impl ServerKey
pub fn unchecked_div_rem_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, T)where
T: IntegerRadixCiphertext,
pub fn unchecked_div_rem_floor_parallelized( &self, numerator: &SignedRadixCiphertext, divisor: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, SignedRadixCiphertext)
Sourcepub fn div_rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> (T, T)where
T: IntegerRadixCiphertext,
pub fn div_rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> (T, T)where
T: IntegerRadixCiphertext,
Computes homomorphically the quotient and remainder of the division between two ciphertexts
§Notes
When the divisor is 0:
-
For unsigned operands, the returned quotient will be the max value (i.e. all bits set to 1), the remainder will have the value of the numerator.
-
For signed operands, remainder will have the same value as the numerator, and, if the numerator is < 0, quotient will be -1 else 1
This behaviour should not be relied on.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg1 = 97;
let msg2 = 14;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically the quotient and remainder:
let (q_res, r_res) = sks.div_rem_parallelized(&ct1, &ct2);
// Decrypt:
let q: u64 = cks.decrypt(&q_res);
let r: u64 = cks.decrypt(&r_res);
assert_eq!(q, msg1 / msg2);
assert_eq!(r, msg1 % msg2);
pub fn smart_div_rem_parallelized<T>(
&self,
numerator: &mut T,
divisor: &mut T,
) -> (T, T)where
T: IntegerRadixCiphertext,
pub fn unchecked_div_assign_parallelized<T>(
&self,
numerator: &mut T,
divisor: &T,
)where
T: IntegerRadixCiphertext,
pub fn unchecked_div_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_div_assign_parallelized<T>(
&self,
numerator: &mut T,
divisor: &mut T,
)where
T: IntegerRadixCiphertext,
pub fn smart_div_parallelized<T>(&self, numerator: &mut T, divisor: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn div_assign_parallelized<T>(&self, numerator: &mut T, divisor: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn div_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn div_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically the quotient of the division between two ciphertexts
§Note
If you need both the quotient and remainder use Self::div_rem_parallelized.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg1 = 97;
let msg2 = 14;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically a division:
let ct_res = sks.div_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 / msg2);
pub fn unchecked_rem_assign_parallelized<T>(
&self,
numerator: &mut T,
divisor: &T,
)where
T: IntegerRadixCiphertext,
pub fn unchecked_rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_rem_assign_parallelized<T>(
&self,
numerator: &mut T,
divisor: &mut T,
)where
T: IntegerRadixCiphertext,
pub fn smart_rem_parallelized<T>(&self, numerator: &mut T, divisor: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn rem_assign_parallelized<T>(&self, numerator: &mut T, divisor: &T)where
T: IntegerRadixCiphertext,
Sourcepub fn rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically the remainder (rest) of the division between two ciphertexts
§Note
If you need both the quotient and remainder use Self::div_rem_parallelized.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg1 = 97;
let msg2 = 14;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);
// Compute homomorphically the remainder:
let ct_res = sks.rem_parallelized(&ct1, &ct2);
// Decrypt:
let dec_result: u64 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 % msg2);
Sourcepub fn checked_div_rem_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, T, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn checked_div_rem_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, T, BooleanBlock)where
T: IntegerRadixCiphertext,
Computes homomorphically the quotient and remainder of the division between two ciphertexts
Returns an additional flag indicating if the divisor was 0
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = 97u8;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(0u8);
// Compute homomorphically a division:
let (ct_q, ct_r, div_by_0) = sks.checked_div_rem_parallelized(&ct1, &ct2);
// Decrypt:
let div_by_0 = cks.decrypt_bool(&div_by_0);
assert!(div_by_0);
let q: u8 = cks.decrypt(&ct_q);
assert_eq!(u8::MAX, q);
let r: u8 = cks.decrypt(&ct_r);
assert_eq!(msg, r);
Sourcepub fn checked_div_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn checked_div_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
Computes homomorphically the quotient of the division between two ciphertexts
Returns an additional flag indicating if the divisor was 0
§Note
If you need both the quotient and remainder use Self::div_rem_parallelized.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = 97u8;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(0u8);
// Compute homomorphically a division:
let (ct_res, div_by_0) = sks.checked_div_parallelized(&ct1, &ct2);
// Decrypt:
let div_by_0 = cks.decrypt_bool(&div_by_0);
assert!(div_by_0);
let dec_result: u8 = cks.decrypt(&ct_res);
assert_eq!(u8::MAX, dec_result);
Sourcepub fn checked_rem_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn checked_rem_parallelized<T>(
&self,
numerator: &T,
divisor: &T,
) -> (T, BooleanBlock)where
T: IntegerRadixCiphertext,
Computes homomorphically the remainder (rest) of the division between two ciphertexts
Returns an additional flag indicating if the divisor was 0
§Note
If you need both the quotient and remainder use Self::checked_div_rem_parallelized.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = 97u8;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(0u8);
// Compute homomorphically the remainder:
let (ct_res, rem_by_0) = sks.checked_rem_parallelized(&ct1, &ct2);
// Decrypt:
let rem_by_0 = cks.decrypt_bool(&rem_by_0);
assert!(rem_by_0);
let dec_result: u8 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg);
Source§impl ServerKey
impl ServerKey
Sourcepub fn switch_modulus_and_compress_parallelized(
&self,
ct: &RadixCiphertext,
) -> CompressedModulusSwitchedRadixCiphertext
pub fn switch_modulus_and_compress_parallelized( &self, ct: &RadixCiphertext, ) -> CompressedModulusSwitchedRadixCiphertext
Compresses a ciphertext to have a smaller serialization size
See CompressedModulusSwitchedRadixCiphertext
for usage
Sourcepub fn decompress_parallelized(
&self,
compressed_ct: &CompressedModulusSwitchedRadixCiphertext,
) -> RadixCiphertext
pub fn decompress_parallelized( &self, compressed_ct: &CompressedModulusSwitchedRadixCiphertext, ) -> RadixCiphertext
Decompresses a compressed ciphertext This operation costs a PBS
See CompressedModulusSwitchedRadixCiphertext
for usage
Sourcepub fn switch_modulus_and_compress_signed_parallelized(
&self,
ct: &SignedRadixCiphertext,
) -> CompressedModulusSwitchedSignedRadixCiphertext
pub fn switch_modulus_and_compress_signed_parallelized( &self, ct: &SignedRadixCiphertext, ) -> CompressedModulusSwitchedSignedRadixCiphertext
Compresses a signed ciphertext to have a smaller serialization size
See CompressedModulusSwitchedSignedRadixCiphertext
for usage
Sourcepub fn decompress_signed_parallelized(
&self,
compressed_ct: &CompressedModulusSwitchedSignedRadixCiphertext,
) -> SignedRadixCiphertext
pub fn decompress_signed_parallelized( &self, compressed_ct: &CompressedModulusSwitchedSignedRadixCiphertext, ) -> SignedRadixCiphertext
Decompresses a signed compressed ciphertext This operation costs a PBS
See CompressedModulusSwitchedSignedRadixCiphertext
for usage
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_block_mul_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
pub fn unchecked_block_mul_assign_parallelized<T>(
&self,
ct_left: &mut T,
ct_right: &Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertext encrypting an integer value and another encrypting a shortint value.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 170;
let clear_2 = 3;
// Encrypt two messages
let mut ct_left = cks.encrypt(clear_1);
let ct_right = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
sks.unchecked_block_mul_assign_parallelized(&mut ct_left, &ct_right, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_left);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn unchecked_block_mul_parallelized<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_block_mul_parallelized<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertexts encrypting an integer value and another encrypting a shortint value.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 55;
let clear_2 = 3;
// Encrypt two messages
let ct_left = cks.encrypt(clear_1);
let ct_right = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.unchecked_block_mul_parallelized(&ct_left, &ct_right, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn smart_block_mul_parallelized<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_block_mul_parallelized<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertext encrypting integer value and another encrypting a shortint value.
The result is returned as a new ciphertext.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 170;
let clear_2 = 3;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.smart_block_mul_parallelized(&mut ctxt_1, &mut ctxt_2, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn block_mul_parallelized<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn block_mul_parallelized<T>(
&self,
ct1: &T,
ct2: &Ciphertext,
index: usize,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between a ciphertext encrypting integer value and another encrypting a shortint value.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 170;
let clear_2 = 3;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt_one_block(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.block_mul_parallelized(&ctxt_1, &ctxt_2, 0);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
pub fn block_mul_assign_parallelized<T>(
&self,
ct1: &mut T,
ct2: &Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
pub fn smart_block_mul_assign_parallelized<T>(
&self,
ct1: &mut T,
ct2: &mut Ciphertext,
index: usize,
)where
T: IntegerRadixCiphertext,
Sourcepub fn unchecked_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &T)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is assigned to the ct_left
ciphertext.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 255;
let clear_2 = 143;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.unchecked_mul_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn unchecked_mul_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_mul_parallelized<T>(&self, lhs: &T, rhs: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
This function computes the operation without checking if it exceeds the capacity of the ciphertext.
The result is returned as a new ciphertext.
§Warning
- Multithreaded
Sourcepub fn smart_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &mut T)where
T: IntegerRadixCiphertext,
pub fn smart_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &mut T)where
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
The result is assigned to the ct_left
ciphertext.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 170;
let clear_2 = 6;
// Encrypt two messages
let mut ctxt_1 = cks.encrypt(clear_1);
let mut ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.smart_mul_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
Sourcepub fn smart_mul_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_mul_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
The result is returned as a new ciphertext.
§Warning
- Multithreaded
Sourcepub fn mul_parallelized<T>(&self, ct1: &T, ct2: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn mul_parallelized<T>(&self, ct1: &T, ct2: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a multiplication between two ciphertexts encrypting integer values.
The result is assigned to the ct_left
ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Warning
- Multithreaded
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 170;
let clear_2 = 6;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let ct_res = sks.mul_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res: u64 = cks.decrypt(&ct_res);
assert_eq!((clear_1 * clear_2) % 256, res);
pub fn mul_assign_parallelized<T>(&self, ct1: &mut T, ct2: &T)where
T: IntegerRadixCiphertext,
pub fn unchecked_unsigned_overflowing_mul_parallelized( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_unsigned_overflowing_mul_assign_parallelized( &self, lhs: &mut RadixCiphertext, rhs: &RadixCiphertext, ) -> BooleanBlock
Sourcepub fn unsigned_overflowing_mul_parallelized(
&self,
ct1: &RadixCiphertext,
ct2: &RadixCiphertext,
) -> (RadixCiphertext, BooleanBlock)
pub fn unsigned_overflowing_mul_parallelized( &self, ct1: &RadixCiphertext, ct2: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
Computes homomorphically a multiplication along with an overflow flag
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = 128u8;
let clear_2 = 5u8;
// Encrypt two messages
let ctxt_1 = cks.encrypt(clear_1);
let ctxt_2 = cks.encrypt(clear_2);
// Compute homomorphically a multiplication
let (ct_res, ct_overflowed) = sks.unsigned_overflowing_mul_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res: u8 = cks.decrypt(&ct_res);
let overflowed = cks.decrypt_bool(&ct_overflowed);
let (expected_result, expected_overflowed) = clear_1.overflowing_mul(clear_2);
assert_eq!(res, expected_result);
assert_eq!(overflowed, expected_overflowed);
pub fn unsigned_overflowing_mul_assign_parallelized( &self, ct1: &mut RadixCiphertext, ct2: &RadixCiphertext, ) -> BooleanBlock
Sourcepub fn signed_overflowing_mul_parallelized(
&self,
lhs: &SignedRadixCiphertext,
rhs: &SignedRadixCiphertext,
) -> (SignedRadixCiphertext, BooleanBlock)
pub fn signed_overflowing_mul_parallelized( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Computes homomorphically a multiplication along with an overflow flag
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let clear_1 = -128i8;
let clear_2 = 5i8;
// Encrypt two messages
let ctxt_1 = cks.encrypt_signed(clear_1);
let ctxt_2 = cks.encrypt_signed(clear_2);
// Compute homomorphically a multiplication
let (ct_res, ct_overflowed) = sks.signed_overflowing_mul_parallelized(&ctxt_1, &ctxt_2);
// Decrypt
let res: i8 = cks.decrypt_signed(&ct_res);
let overflowed = cks.decrypt_bool(&ct_overflowed);
let (expected_result, expected_overflowed) = clear_1.overflowing_mul(clear_2);
assert_eq!(res, expected_result);
assert_eq!(overflowed, expected_overflowed);
Source§impl ServerKey
impl ServerKey
Sourcepub fn smart_neg_parallelized<T>(&self, ctxt: &mut T) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_neg_parallelized<T>(&self, ctxt: &mut T) -> Twhere
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
// Encrypt two messages:
let mut ctxt = cks.encrypt(msg);
// Compute homomorphically a negation
let ct_res = sks.smart_neg_parallelized(&mut ctxt);
// Decrypt
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(255, dec);
Sourcepub fn neg_parallelized<T>(&self, ctxt: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn neg_parallelized<T>(&self, ctxt: &T) -> Twhere
T: IntegerRadixCiphertext,
Homomorphically computes the opposite of a ciphertext encrypting an integer message.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 1u64;
// Encrypt two messages:
let ctxt = cks.encrypt(msg);
// Compute homomorphically a negation
let ct_res = sks.neg_parallelized(&ctxt);
// Decrypt
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(255, dec);
Source§impl ServerKey
impl ServerKey
pub fn unchecked_rotate_right_parallelized<T>(
&self,
ct: &T,
n: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_rotate_right_assign_parallelized<T>(
&self,
ct: &mut T,
n: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_rotate_right_assign_parallelized<T>(
&self,
ct: &mut T,
n: &mut RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_rotate_right_parallelized<T>(
&self,
ct: &mut T,
rotate: &mut RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
Sourcepub fn rotate_right_assign_parallelized<T>(
&self,
ct: &mut T,
rotate: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn rotate_right_assign_parallelized<T>(
&self,
ct: &mut T,
rotate: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let ct = cks.encrypt(msg as u64);
let n_ct = cks.encrypt(n as u64);
let ct_res = sks.rotate_right_parallelized(&ct, &n_ct);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_right(n as u32) as u64, dec);
pub fn rotate_right_parallelized<T>(
&self,
ct: &T,
rotate: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_rotate_left_parallelized<T>(
&self,
ct_left: &T,
n: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_rotate_left_assign_parallelized<T>(
&self,
ct: &mut T,
n: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_rotate_left_assign_parallelized<T>(
&self,
ct: &mut T,
n: &mut RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_rotate_left_parallelized<T>(
&self,
ct: &mut T,
rotate: &mut RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn rotate_left_assign_parallelized<T>(
&self,
ct: &mut T,
rotate: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
Sourcepub fn rotate_left_parallelized<T>(&self, ct: &T, rotate: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn rotate_left_parallelized<T>(&self, ct: &T, rotate: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is returned as a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let ct = cks.encrypt(msg as u64);
let n_ct = cks.encrypt(n as u64);
let ct_res = sks.rotate_left_parallelized(&ct, &n_ct);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_left(n as u32) as u64, dec);
Source§impl ServerKey
impl ServerKey
pub fn overflowing_scalar_add_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, ) -> BooleanBlock
pub fn overflowing_scalar_add_parallelized<T, Scalar>( &self, lhs: &T, scalar: Scalar, ) -> (T, BooleanBlock)
pub fn unsigned_overflowing_scalar_add_assign_parallelized<Scalar>( &self, lhs: &mut RadixCiphertext, scalar: Scalar, ) -> BooleanBlock
pub fn unsigned_overflowing_scalar_add_parallelized<Scalar>( &self, lhs: &RadixCiphertext, scalar: Scalar, ) -> (RadixCiphertext, BooleanBlock)
pub fn signed_overflowing_scalar_add_assign_parallelized<Scalar>( &self, lhs: &mut SignedRadixCiphertext, scalar: Scalar, ) -> BooleanBlock
pub fn signed_overflowing_scalar_add_parallelized<Scalar>( &self, lhs: &SignedRadixCiphertext, scalar: Scalar, ) -> (SignedRadixCiphertext, BooleanBlock)
Sourcepub fn smart_scalar_add_parallelized<T, Scalar>(
&self,
ct: &mut T,
scalar: Scalar,
) -> T
pub fn smart_scalar_add_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, ) -> T
Computes homomorphically the addition of ciphertext with a scalar.
The result is returned in a new ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 4;
let scalar = 40;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.smart_scalar_add_parallelized(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + scalar, dec);
Sourcepub fn smart_scalar_add_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
scalar: Scalar,
)
pub fn smart_scalar_add_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )
Computes homomorphically the addition of ciphertext with a scalar.
The result is assigned to the ct_left
ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 129;
let scalar = 40;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
sks.smart_scalar_add_assign_parallelized(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg + scalar, dec);
Sourcepub fn scalar_add_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
pub fn scalar_add_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
Computes homomorphically the addition of ciphertext with a scalar.
The result is returned in a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 4;
let scalar = 40;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.scalar_add_parallelized(&ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + scalar, dec);
Sourcepub fn scalar_add_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
scalar: Scalar,
)
pub fn scalar_add_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )
Computes homomorphically the addition of ciphertext with a scalar.
The result is assigned to the ct_left
ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 129;
let scalar = 40;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
sks.scalar_add_assign_parallelized(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg + scalar, dec);
Source§impl ServerKey
impl ServerKey
pub fn unchecked_scalar_bitand_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T
pub fn unchecked_scalar_bitand_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
pub fn smart_scalar_bitand_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T
pub fn smart_scalar_bitand_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
Sourcepub fn scalar_bitand_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
pub fn scalar_bitand_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
Computes homomorphically a bitand between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14u8;
let msg2 = 97u8;
let ct1 = cks.encrypt(msg1);
let ct_res = sks.scalar_bitand_parallelized(&ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 & msg2);
Sourcepub fn scalar_bitand_assign_parallelized<T, Scalar>(
&self,
lhs: &mut T,
rhs: Scalar,
)
pub fn scalar_bitand_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
Computes homomorphically a bitand between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 123u8;
let msg2 = 34u8;
let mut ct1 = cks.encrypt(msg1);
sks.scalar_bitand_assign_parallelized(&mut ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct1);
assert_eq!(dec_result, msg1 & msg2);
pub fn unchecked_scalar_bitor_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T
pub fn unchecked_scalar_bitor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
pub fn smart_scalar_bitor_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T
pub fn smart_scalar_bitor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
Sourcepub fn scalar_bitor_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
pub fn scalar_bitor_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
Computes homomorphically a bitor between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14u8;
let msg2 = 97u8;
let ct1 = cks.encrypt(msg1);
let ct_res = sks.scalar_bitor_parallelized(&ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 | msg2);
Sourcepub fn scalar_bitor_assign_parallelized<T, Scalar>(
&self,
lhs: &mut T,
rhs: Scalar,
)
pub fn scalar_bitor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
Computes homomorphically a bitor between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 123u8;
let msg2 = 34u8;
let mut ct1 = cks.encrypt(msg1);
sks.scalar_bitor_assign_parallelized(&mut ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct1);
assert_eq!(dec_result, msg1 | msg2);
pub fn unchecked_scalar_bitxor_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T
pub fn unchecked_scalar_bitxor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
pub fn smart_scalar_bitxor_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T
pub fn smart_scalar_bitxor_assign_parallelized<T, Scalar>( &self, lhs: &mut RadixCiphertext, rhs: Scalar, )
Sourcepub fn scalar_bitxor_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
pub fn scalar_bitxor_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
Computes homomorphically a bitxor between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 14u8;
let msg2 = 97u8;
let ct1 = cks.encrypt(msg1);
let ct_res = sks.scalar_bitxor_parallelized(&ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct_res);
assert_eq!(dec_result, msg1 ^ msg2);
Sourcepub fn scalar_bitxor_assign_parallelized<T, Scalar>(
&self,
lhs: &mut T,
rhs: Scalar,
)
pub fn scalar_bitxor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )
Computes homomorphically a bitxor between a ciphertexts and a clear value
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg1 = 123u8;
let msg2 = 34u8;
let mut ct1 = cks.encrypt(msg1);
sks.scalar_bitxor_assign_parallelized(&mut ct1, msg2);
// Decrypt:
let dec_result: u8 = cks.decrypt(&ct1);
assert_eq!(dec_result, msg1 ^ msg2);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_scalar_eq_parallelized<T, Scalar>(
&self,
lhs: &T,
rhs: Scalar,
) -> BooleanBlock
pub fn unchecked_scalar_eq_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
Compares for equality a ciphertexts and a clear value
Returns a ciphertext containing 1 if lhs == rhs, otherwise 0
Requires carry bits to be empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let size = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg1 = 14u64;
let msg2 = 97u64;
let ct1 = cks.encrypt(msg1);
let ct_res = sks.unchecked_scalar_eq_parallelized(&ct1, msg2);
// Decrypt:
let dec_result = cks.decrypt_bool(&ct_res);
assert_eq!(dec_result, msg1 == msg2);
pub fn unchecked_scalar_ne_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_eq_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_eq_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_ne_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_ne_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn unchecked_scalar_gt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn unchecked_scalar_ge_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn unchecked_scalar_lt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn unchecked_scalar_le_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn unchecked_scalar_max_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T
pub fn unchecked_scalar_min_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T
pub fn smart_scalar_gt_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_ge_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_lt_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_le_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock
pub fn smart_scalar_max_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T
pub fn smart_scalar_min_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T
pub fn scalar_gt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_ge_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_lt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_le_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock
pub fn scalar_max_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
pub fn scalar_min_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T
Source§impl ServerKey
impl ServerKey
pub fn unchecked_scalar_div_parallelized<T>(
&self,
numerator: &RadixCiphertext,
divisor: T,
) -> RadixCiphertextwhere
T: Reciprocable,
Sourcepub fn unchecked_signed_scalar_div_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn unchecked_signed_scalar_div_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
§Note
This division rounds (truncates) the quotient towards zero
Sourcepub fn unchecked_signed_scalar_div_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn unchecked_signed_scalar_div_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
§Note
- This division rounds (truncates) the quotient towards 0
Sourcepub fn unchecked_signed_scalar_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn unchecked_signed_scalar_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
§Note
- This division rounds (truncates) the quotient towards 0
- If you need both the quotient and remainder use Self::unchecked_signed_scalar_div_rem_parallelized instead.
Sourcepub fn signed_scalar_div_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn signed_scalar_div_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
Computes and returns the quotient and remainder of the division between a signed ciphertext and a signed clear value.
§Note
- This division rounds (truncates) the quotient towards 0
Sourcepub fn signed_scalar_div_assign_parallelized<T>(
&self,
numerator: &mut SignedRadixCiphertext,
divisor: T,
)where
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn signed_scalar_div_assign_parallelized<T>(
&self,
numerator: &mut SignedRadixCiphertext,
divisor: T,
)where
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
Computes the quotient of the division between a signed ciphertext and a signed clear value and assigns the result to the input ciphertext.
§Note
- This division rounds (truncates) the quotient towards 0
Sourcepub fn signed_scalar_div_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn signed_scalar_div_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
Computes and returns the quotient of the division between a signed ciphertext and a signed clear value.
§Note
- This division rounds (truncates) the quotient towards 0
- If you need both the quotient and remainder use Self::signed_scalar_div_rem_parallelized instead.
Sourcepub fn signed_scalar_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn signed_scalar_rem_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
Computes and returns the remainder of the division between a signed ciphertext and a signed clear value.
§Note
- If you need both the quotient and remainder use Self::signed_scalar_div_rem_parallelized instead.
Sourcepub fn signed_scalar_rem_assign_parallelized<T>(
&self,
numerator: &mut SignedRadixCiphertext,
divisor: T,
)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn signed_scalar_rem_assign_parallelized<T>(
&self,
numerator: &mut SignedRadixCiphertext,
divisor: T,
)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
Computes the remainder of the division between a signed ciphertext and a signed clear value and assigns the result to the input ciphertext.
Sourcepub fn unchecked_signed_scalar_div_floor_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn unchecked_signed_scalar_div_floor_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> SignedRadixCiphertextwhere
T: SignedReciprocable,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
§Note
This division rounds the quotient towards minus infinity
Sourcepub fn unchecked_signed_scalar_div_rem_floor_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
pub fn unchecked_signed_scalar_div_rem_floor_parallelized<T>(
&self,
numerator: &SignedRadixCiphertext,
divisor: T,
) -> (SignedRadixCiphertext, SignedRadixCiphertext)where
T: SignedReciprocable + ScalarMultiplier,
<<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,
§Note
This division rounds the quotient towards minus infinity
pub fn unchecked_scalar_div_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> (RadixCiphertext, RadixCiphertext)
pub fn unchecked_scalar_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> RadixCiphertext
pub fn smart_scalar_div_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )
pub fn smart_scalar_rem_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )
pub fn smart_scalar_div_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> RadixCiphertext
pub fn smart_scalar_rem_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> RadixCiphertext
pub fn smart_scalar_div_rem_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> (RadixCiphertext, RadixCiphertext)
pub fn scalar_div_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )
pub fn scalar_rem_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )
Sourcepub fn scalar_div_parallelized<T>(
&self,
numerator: &RadixCiphertext,
divisor: T,
) -> RadixCiphertext
pub fn scalar_div_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> RadixCiphertext
Computes homomorphically a division of a ciphertext by a scalar.
§Note
If you need both the quotient and the remainder of the division use Self::scalar_div_rem_parallelized.
§Panics
Panics if scalar is zero.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, size);
let msg = 230u8;
let scalar = 12u8;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar division:
let ct_res = sks.scalar_div_parallelized(&ct, scalar);
let decrypted: u8 = cks.decrypt(&ct_res);
assert_eq!(msg / scalar, decrypted);
Sourcepub fn scalar_rem_parallelized<T>(
&self,
numerator: &RadixCiphertext,
divisor: T,
) -> RadixCiphertext
pub fn scalar_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> RadixCiphertext
Computes homomorphically the remainder of the division of a ciphertext by a scalar.
§Note
If you need both the quotient and the remainder of the division use Self::scalar_div_rem_parallelized.
§Panics
Panics if scalar is zero.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, size);
let msg = 230u8;
let scalar = 12u8;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar division:
let ct_res = sks.scalar_rem_parallelized(&ct, scalar);
let decrypted: u8 = cks.decrypt(&ct_res);
assert_eq!(msg % scalar, decrypted);
Sourcepub fn scalar_div_rem_parallelized<T>(
&self,
numerator: &RadixCiphertext,
divisor: T,
) -> (RadixCiphertext, RadixCiphertext)
pub fn scalar_div_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> (RadixCiphertext, RadixCiphertext)
Computes homomorphically the euclidean the division of a ciphertext by a scalar.
§Panics
Panics if scalar is zero.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, size);
let msg = 230u8;
let scalar = 12u8;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar division:
let (q, r) = sks.scalar_div_rem_parallelized(&ct, scalar);
let decrypted_quotient: u8 = cks.decrypt(&q);
let decrypted_remainder: u8 = cks.decrypt(&r);
assert_eq!(msg / scalar, decrypted_quotient);
assert_eq!(msg % scalar, decrypted_remainder);
Source§impl ServerKey
impl ServerKey
pub fn unchecked_scalar_mul_parallelized<T, Scalar>( &self, ct: &T, scalar: Scalar, ) -> T
pub fn unchecked_scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )
Sourcepub fn smart_scalar_mul_parallelized<T, Scalar>(
&self,
lhs: &mut T,
scalar: Scalar,
) -> T
pub fn smart_scalar_mul_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, ) -> T
Computes homomorphically a multiplication between a scalar and a ciphertext.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let modulus = 1 << 8;
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 230;
let scalar = 376;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_scalar_mul_parallelized(&mut ct, scalar);
// Decrypt:
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(msg * scalar % modulus, clear);
pub fn smart_scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )
Sourcepub fn scalar_mul_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
pub fn scalar_mul_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
Computes homomorphically a multiplication between a scalar and a ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let modulus = 1 << 8;
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 230;
let scalar = 376;
let ct = cks.encrypt(msg);
// Compute homomorphically a scalar multiplication:
let ct_res = sks.scalar_mul_parallelized(&ct, scalar);
// Decrypt:
let clear: u64 = cks.decrypt(&ct_res);
assert_eq!(msg * scalar % modulus, clear);
pub fn scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )
Source§impl ServerKey
impl ServerKey
Sourcepub fn smart_scalar_rotate_right_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
) -> T
pub fn smart_scalar_rotate_right_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
If necessary the carries of the input will be cleaned beforehand, but its value won’t change, the result is returned in a new ciphertext
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let mut ct = cks.encrypt(msg as u64);
let ct_res = sks.smart_scalar_rotate_right_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn smart_scalar_rotate_right_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn smart_scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is assigned to the input ciphertext
If necessary carries will be cleaned beforehand
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let mut ct = cks.encrypt(msg as u64);
sks.smart_scalar_rotate_right_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn scalar_rotate_right_parallelized<T, Scalar>(
&self,
ct_right: &T,
n: Scalar,
) -> T
pub fn scalar_rotate_right_parallelized<T, Scalar>( &self, ct_right: &T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let ct = cks.encrypt(msg as u64);
let ct_res = sks.scalar_rotate_right_parallelized(&ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn scalar_rotate_right_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is assigned to the input ciphertext
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let mut ct = cks.encrypt(msg as u64);
sks.scalar_rotate_right_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn unchecked_scalar_rotate_right_parallelized<T, Scalar>(
&self,
ct: &T,
n: Scalar,
) -> T
pub fn unchecked_scalar_rotate_right_parallelized<T, Scalar>( &self, ct: &T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let ct = cks.encrypt(msg as u64);
let ct_res = sks.unchecked_scalar_rotate_right_parallelized(&ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn unchecked_scalar_rotate_right_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn unchecked_scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the right by a specified amount,
n
, wrapping the truncated bits to the beginning of the resulting integer.
The result is assigned to the input ciphertext
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2;
let mut ct = cks.encrypt(msg as u64);
sks.unchecked_scalar_rotate_right_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_right(n) as u64, dec);
Sourcepub fn smart_scalar_rotate_left_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
) -> T
pub fn smart_scalar_rotate_left_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
If necessary the carries of the input will be cleaned beforehand, but its value won’t change, the result is returned in a new ciphertext
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let mut ct = cks.encrypt(msg as u64);
let ct_res = sks.smart_scalar_rotate_left_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_left(n) as u64, dec);
Sourcepub fn smart_scalar_rotate_left_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn smart_scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is assigned to the input ciphertext
If necessary carries will be cleaned beforehand
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let mut ct = cks.encrypt(msg as u64);
sks.smart_scalar_rotate_left_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_left(n) as u64, dec);
Sourcepub fn scalar_rotate_left_parallelized<T, Scalar>(
&self,
ct_left: &T,
n: Scalar,
) -> T
pub fn scalar_rotate_left_parallelized<T, Scalar>( &self, ct_left: &T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let ct = cks.encrypt(msg as u64);
let ct_res = sks.scalar_rotate_left_parallelized(&ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_left(n) as u64, dec);
Sourcepub fn scalar_rotate_left_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is assigned to the input ciphertext
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let mut ct = cks.encrypt(msg as u64);
sks.scalar_rotate_left_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_left(n) as u64, dec);
Sourcepub fn unchecked_scalar_rotate_left_parallelized<T, Scalar>(
&self,
ct: &T,
n: Scalar,
) -> T
pub fn unchecked_scalar_rotate_left_parallelized<T, Scalar>( &self, ct: &T, n: Scalar, ) -> T
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let ct = cks.encrypt(msg as u64);
let ct_res = sks.unchecked_scalar_rotate_left_parallelized(&ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg.rotate_left(n) as u64, dec);
Sourcepub fn unchecked_scalar_rotate_left_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
n: Scalar,
)
pub fn unchecked_scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
Computes homomorphically a rotation of bits.
Shifts the bits to the left by a specified amount,
n
, wrapping the truncated bits to the end of the resulting integer.
The result is assigned to the input ciphertext
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128u8;
let n = 2u32;
let mut ct = cks.encrypt(msg as u64);
sks.unchecked_scalar_rotate_left_assign_parallelized(&mut ct, n);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg.rotate_left(n) as u64, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_scalar_right_shift_parallelized<T, Scalar>(
&self,
ct: &T,
shift: Scalar,
) -> T
pub fn unchecked_scalar_right_shift_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
Computes homomorphically a right shift.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output’s carries will be clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128;
let shift = 2;
let ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
let ct_res = sks.unchecked_scalar_right_shift_parallelized(&ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg >> shift, dec);
Sourcepub fn unchecked_scalar_right_shift_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
shift: Scalar,
)
pub fn unchecked_scalar_right_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
Computes homomorphically a right shift.
§Requirements
- The blocks parameter’s carry space have at at least (message_bits - 1)
- The input ciphertext carry buffer is empty / clean
§Output
- The carry of the output blocks will be empty / clean
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 18;
let shift = 4;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
sks.unchecked_scalar_right_shift_assign_parallelized(&mut ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg >> shift, dec);
pub fn unchecked_scalar_right_shift_arithmetic_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
pub fn unchecked_scalar_right_shift_arithmetic_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
pub fn unchecked_scalar_right_shift_logical_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
Sourcepub fn scalar_right_shift_parallelized<T, Scalar>(
&self,
ct: &T,
shift: Scalar,
) -> T
pub fn scalar_right_shift_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
Computes homomorphically a right shift.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128;
let shift = 2;
let ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
let ct_res = sks.scalar_right_shift_parallelized(&ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg >> shift, dec);
Sourcepub fn scalar_right_shift_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
shift: Scalar,
)
pub fn scalar_right_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
Computes homomorphically a right shift.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 18;
let shift = 4;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
sks.scalar_right_shift_assign_parallelized(&mut ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg >> shift, dec);
Sourcepub fn unchecked_scalar_left_shift_parallelized<T, Scalar>(
&self,
ct_left: &T,
shift: Scalar,
) -> T
pub fn unchecked_scalar_left_shift_parallelized<T, Scalar>( &self, ct_left: &T, shift: Scalar, ) -> T
Computes homomorphically a left shift by a scalar.
The result is returned as a new ciphertext.
§Requirements
- The blocks parameter’s carry space have at least one more bit than message space
- The input ciphertext carry buffer is empty / clean
§Output
- The output ciphertext carry buffers will be clean / empty
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 21;
let shift = 2;
let ct1 = cks.encrypt(msg);
// Compute homomorphically a left shift:
let ct_res = sks.unchecked_scalar_left_shift_parallelized(&ct1, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg << shift, dec);
Sourcepub fn unchecked_scalar_left_shift_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
shift: Scalar,
)
pub fn unchecked_scalar_left_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
Computes homomorphically a left shift by a scalar.
The result is assigned in the input ciphertext
§Requirements
- The blocks parameter’s carry space have at at least (message_bits - 1)
- The input ciphertext carry buffer is empty / clean
§Output
- The ct carry buffers will be clean / empty afterwards
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 13;
let shift = 2;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a left shift:
sks.unchecked_scalar_left_shift_assign_parallelized(&mut ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg << shift, dec);
Sourcepub fn scalar_left_shift_parallelized<T, Scalar>(
&self,
ct_left: &T,
shift: Scalar,
) -> T
pub fn scalar_left_shift_parallelized<T, Scalar>( &self, ct_left: &T, shift: Scalar, ) -> T
Computes homomorphically a left shift by a scalar.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 21;
let shift = 2;
let ct1 = cks.encrypt(msg);
// Compute homomorphically a left shift:
let ct_res = sks.scalar_left_shift_parallelized(&ct1, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg << shift, dec);
Sourcepub fn scalar_left_shift_assign_parallelized<T, Scalar>(
&self,
ct: &mut T,
shift: Scalar,
)
pub fn scalar_left_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
Computes homomorphically a left shift by a scalar.
The result is assigned in the input ciphertext
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 13;
let shift = 2;
let mut ct = cks.encrypt(msg);
// Compute homomorphically a right shift:
sks.scalar_left_shift_assign_parallelized(&mut ct, shift);
// Decrypt:
let dec: u64 = cks.decrypt(&ct);
assert_eq!(msg << shift, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn smart_scalar_sub_parallelized<T, Scalar>(
&self,
ct: &mut T,
scalar: Scalar,
) -> T
pub fn smart_scalar_sub_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, ) -> T
Computes homomorphically a subtraction of a ciphertext by a scalar.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 165;
let scalar = 112;
let mut ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.smart_scalar_sub_parallelized(&mut ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg - scalar, dec);
pub fn smart_scalar_sub_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )
Sourcepub fn scalar_sub_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
pub fn scalar_sub_parallelized<T, Scalar>(&self, ct: &T, scalar: Scalar) -> T
Computes homomorphically a subtraction of a ciphertext by a scalar.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 165;
let scalar = 112;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.scalar_sub_parallelized(&ct, scalar);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg - scalar, dec);
pub fn scalar_sub_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )
pub fn unchecked_left_scalar_sub<Scalar, T>(&self, scalar: Scalar, rhs: &T) -> T
pub fn is_left_scalar_sub_possible<Scalar, T>( &self, scalar: Scalar, rhs: &T, ) -> Result<(), CheckError>
pub fn smart_left_scalar_sub_parallelized<Scalar, T>( &self, scalar: Scalar, rhs: &mut T, ) -> T
pub fn left_scalar_sub_parallelized<Scalar, T>( &self, scalar: Scalar, rhs: &T, ) -> T
pub fn unsigned_overflowing_scalar_sub_assign_parallelized<T>( &self, lhs: &mut RadixCiphertext, scalar: T, ) -> BooleanBlock
pub fn unsigned_overflowing_scalar_sub_parallelized<T>( &self, lhs: &RadixCiphertext, scalar: T, ) -> (RadixCiphertext, BooleanBlock)
pub fn signed_overflowing_scalar_sub_assign_parallelized<Scalar>( &self, lhs: &mut SignedRadixCiphertext, scalar: Scalar, ) -> BooleanBlock
pub fn signed_overflowing_scalar_sub_parallelized<Scalar>( &self, lhs: &SignedRadixCiphertext, scalar: Scalar, ) -> (SignedRadixCiphertext, BooleanBlock)
Source§impl ServerKey
impl ServerKey
pub fn unchecked_right_shift_parallelized<T>(
&self,
ct_left: &T,
shift: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_right_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_right_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &mut RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_right_shift_parallelized<T>(
&self,
ct: &mut T,
shift: &mut RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn right_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
Sourcepub fn right_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn right_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a right shift by an encrypted amount
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 128;
let shift = 2;
let ct = cks.encrypt(msg);
let shift_ct = cks.encrypt(shift as u64);
// Compute homomorphically a right shift:
let ct_res = sks.right_shift_parallelized(&ct, &shift_ct);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg >> shift, dec);
Sourcepub fn unchecked_left_shift_parallelized<T>(
&self,
ct_left: &T,
shift: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn unchecked_left_shift_parallelized<T>(
&self,
ct_left: &T,
shift: &RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
left shift by and encrypted amount
This requires:
- ct to have clean carries
- shift to have clean carries
- the number of bits in the block to be >= 3
Sourcepub fn unchecked_left_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn unchecked_left_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
left shift by and encrypted amount
This requires:
- ct to have clean carries
- shift to have clean carries
- the number of bits in the block to be >= 3
pub fn smart_left_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &mut RadixCiphertext,
)where
T: IntegerRadixCiphertext,
pub fn smart_left_shift_parallelized<T>(
&self,
ct: &mut T,
shift: &mut RadixCiphertext,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn left_shift_assign_parallelized<T>(
&self,
ct: &mut T,
shift: &RadixCiphertext,
)where
T: IntegerRadixCiphertext,
Sourcepub fn left_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
pub fn left_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically a left shift by an encrypted amount.
The result is returned as a new ciphertext.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg = 21;
let shift = 2;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(shift as u64);
// Compute homomorphically a left shift:
let ct_res = sks.left_shift_parallelized(&ct1, &ct2);
// Decrypt:
let dec: u64 = cks.decrypt(&ct_res);
assert_eq!(msg << shift, dec);
Source§impl ServerKey
impl ServerKey
Sourcepub fn smart_sub_parallelized<T>(
&self,
ctxt_left: &mut T,
ctxt_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
pub fn smart_sub_parallelized<T>(
&self,
ctxt_left: &mut T,
ctxt_right: &mut T,
) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1 as u64);
let mut ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
let ct_res = sks.smart_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn smart_sub_assign_parallelized<T>(
&self,
ctxt_left: &mut T,
ctxt_right: &mut T,
)where
T: IntegerRadixCiphertext,
pub fn smart_sub_assign_parallelized<T>(
&self,
ctxt_left: &mut T,
ctxt_right: &mut T,
)where
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1 as u64);
let mut ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
sks.smart_sub_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ctxt_1);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn sub_parallelized<T>(&self, ctxt_left: &T, ctxt_right: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn sub_parallelized<T>(&self, ctxt_left: &T, ctxt_right: &T) -> Twhere
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg_1 as u64);
let ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
let ct_res = sks.sub_parallelized(&ctxt_1, &ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn sub_assign_parallelized<T>(&self, ctxt_left: &mut T, ctxt_right: &T)where
T: IntegerRadixCiphertext,
pub fn sub_assign_parallelized<T>(&self, ctxt_left: &mut T, ctxt_right: &T)where
T: IntegerRadixCiphertext,
Computes homomorphically the subtraction between ct_left and ct_right.
This function, like all “default” operations (i.e. not smart, checked or unchecked), will check that the input ciphertexts block carries are empty and clears them if it’s not the case and the operation requires it. It outputs a ciphertext whose block carries are always empty.
This means that when using only “default” operations, a given operation (like add for example) has always the same performance characteristics from one call to another and guarantees correctness by pre-emptively clearing carries of output ciphertexts.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let msg_1 = 120u8;
let msg_2 = 181u8;
// Encrypt two messages:
let mut ctxt_1 = cks.encrypt(msg_1 as u64);
let ctxt_2 = cks.encrypt(msg_2 as u64);
// Compute homomorphically a subtraction
sks.sub_assign_parallelized(&mut ctxt_1, &ctxt_2);
// Decrypt:
let res: u64 = cks.decrypt(&ctxt_1);
assert_eq!(msg_1.wrapping_sub(msg_2) as u64, res);
Sourcepub fn unsigned_overflowing_sub_parallelized(
&self,
ctxt_left: &RadixCiphertext,
ctxt_right: &RadixCiphertext,
) -> (RadixCiphertext, BooleanBlock)
pub fn unsigned_overflowing_sub_parallelized( &self, ctxt_left: &RadixCiphertext, ctxt_right: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
Computes the subtraction and returns an indicator of overflow
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = 1u8;
let msg_2 = 255u8;
// Encrypt two messages:
let ctxt_1 = cks.encrypt(msg_1);
let ctxt_2 = cks.encrypt(msg_2);
// Compute homomorphically a subtraction
let (result, overflowed) = sks.unsigned_overflowing_sub_parallelized(&ctxt_1, &ctxt_2);
// Decrypt:
let decrypted_result: u8 = cks.decrypt(&result);
let decrypted_overflow = cks.decrypt_bool(&overflowed);
let (expected_result, expected_overflow) = msg_1.overflowing_sub(msg_2);
assert_eq!(expected_result, decrypted_result);
assert_eq!(expected_overflow, decrypted_overflow);
pub fn unchecked_unsigned_overflowing_sub_parallelized( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_signed_overflowing_sub_parallelized( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Sourcepub fn signed_overflowing_sub_parallelized(
&self,
ctxt_left: &SignedRadixCiphertext,
ctxt_right: &SignedRadixCiphertext,
) -> (SignedRadixCiphertext, BooleanBlock)
pub fn signed_overflowing_sub_parallelized( &self, ctxt_left: &SignedRadixCiphertext, ctxt_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)
Computes the subtraction of two signed numbers and returns an indicator of overflow
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg_1 = i8::MIN;
let msg_2 = 1;
// Encrypt two messages:
let ctxt_1 = cks.encrypt_signed(msg_1);
let ctxt_2 = cks.encrypt_signed(msg_2);
// Compute homomorphically a subtraction
let (result, overflowed) = sks.signed_overflowing_sub_parallelized(&ctxt_1, &ctxt_2);
// Decrypt:
let decrypted_result: i8 = cks.decrypt_signed(&result);
let decrypted_overflow = cks.decrypt_bool(&overflowed);
let (expected_result, expected_overflow) = msg_1.overflowing_sub(msg_2);
assert_eq!(expected_result, decrypted_result);
assert_eq!(expected_overflow, decrypted_overflow);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_sum_ciphertexts_vec_parallelized<T>(
&self,
ciphertexts: Vec<T>,
) -> Option<T>where
T: IntegerRadixCiphertext,
pub fn unchecked_sum_ciphertexts_vec_parallelized<T>(
&self,
ciphertexts: Vec<T>,
) -> Option<T>where
T: IntegerRadixCiphertext,
Computes the sum of the ciphertexts in parallel.
-
Returns None if ciphertexts is empty
-
Expects all ciphertexts to have empty carries
-
Expects all ciphertexts to have the same size
Sourcepub fn unchecked_sum_ciphertexts_parallelized<'a, T, C>(
&self,
ciphertexts: C,
) -> Option<T>
pub fn unchecked_sum_ciphertexts_parallelized<'a, T, C>( &self, ciphertexts: C, ) -> Option<T>
Sourcepub fn sum_ciphertexts_parallelized<'a, T, C>(
&self,
ciphertexts: C,
) -> Option<T>
pub fn sum_ciphertexts_parallelized<'a, T, C>( &self, ciphertexts: C, ) -> Option<T>
Computes the sum of the ciphertexts in parallel.
- Returns None if ciphertexts is empty
See Self::unchecked_sum_ciphertexts_parallelized for constraints
Sourcepub fn smart_sum_ciphertexts_parallelized<T, C>(
&self,
ciphertexts: C,
) -> Option<T>
pub fn smart_sum_ciphertexts_parallelized<T, C>( &self, ciphertexts: C, ) -> Option<T>
Computes the sum of the ciphertexts in parallel.
- Returns None if ciphertexts is empty
See Self::unchecked_sum_ciphertexts_parallelized for constraints
Sourcepub fn unchecked_unsigned_overflowing_sum_ciphertexts_vec_parallelized(
&self,
ciphertexts: Vec<RadixCiphertext>,
) -> Option<(RadixCiphertext, BooleanBlock)>
pub fn unchecked_unsigned_overflowing_sum_ciphertexts_vec_parallelized( &self, ciphertexts: Vec<RadixCiphertext>, ) -> Option<(RadixCiphertext, BooleanBlock)>
- Expects all ciphertexts to have empty carries
- Expects all ciphertexts to have the same size
Sourcepub fn unchecked_unsigned_overflowing_sum_ciphertexts_parallelized<'a, C>(
&self,
ciphertexts: C,
) -> Option<(RadixCiphertext, BooleanBlock)>where
C: IntoIterator<Item = &'a RadixCiphertext>,
pub fn unchecked_unsigned_overflowing_sum_ciphertexts_parallelized<'a, C>(
&self,
ciphertexts: C,
) -> Option<(RadixCiphertext, BooleanBlock)>where
C: IntoIterator<Item = &'a RadixCiphertext>,
Computes the sum of the unsigned ciphertexts in parallel. Returns a boolean indicating if the sum overflowed, that is, the result did not fit in a ciphertext.
Sourcepub fn unsigned_overflowing_sum_ciphertexts_parallelized<'a, C>(
&self,
ciphertexts: C,
) -> Option<(RadixCiphertext, BooleanBlock)>where
C: IntoIterator<Item = &'a RadixCiphertext>,
pub fn unsigned_overflowing_sum_ciphertexts_parallelized<'a, C>(
&self,
ciphertexts: C,
) -> Option<(RadixCiphertext, BooleanBlock)>where
C: IntoIterator<Item = &'a RadixCiphertext>,
Computes the sum of the unsigned ciphertexts in parallel. Returns a boolean indicating if the sum overflowed, that is, the result did not fit in a ciphertext.
- Returns None if ciphertexts is empty
See Self::unchecked_sum_ciphertexts_parallelized for constraints
Sourcepub fn smart_unsigned_overflowing_sum_ciphertexts_parallelized<C>(
&self,
ciphertexts: C,
) -> Option<(RadixCiphertext, BooleanBlock)>
pub fn smart_unsigned_overflowing_sum_ciphertexts_parallelized<C>( &self, ciphertexts: C, ) -> Option<(RadixCiphertext, BooleanBlock)>
Computes the sum of the unsigned ciphertexts in parallel. Returns a boolean indicating if the sum overflowed, that is, the result did not fit in a ciphertext.
- Returns None if ciphertexts is empty
See Self::unchecked_sum_ciphertexts_parallelized for constraints
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of ones in the binary representation of ct
- ct must not have any carries
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Sourcepub fn unchecked_count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of zeros in the binary representation of ct
- ct must not have any carries
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Sourcepub fn smart_count_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_count_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of ones in the binary representation of ct
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Sourcepub fn smart_count_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_count_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of zeros in the binary representation of ct
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Sourcepub fn count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of ones in the binary representation of ct
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Sourcepub fn count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of zeros in the binary representation of ct
- The returned result has enough blocks to encrypt 32bits (e.g. 1_1 parameters -> 32 blocks, 3_3 parameters -> 11 blocks == 33 bits)
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_trailing_zeros_parallelized<T>(
&self,
ct: &T,
) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_trailing_zeros_parallelized<T>(
&self,
ct: &T,
) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
See Self::trailing_zeros_parallelized
Expects ct to have clean carries
Sourcepub fn unchecked_trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
See Self::trailing_ones_parallelized
Expects ct to have clean carries
Sourcepub fn unchecked_leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
See Self::leading_zeros_parallelized
Expects ct to have clean carries
Sourcepub fn unchecked_leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
See Self::leading_ones_parallelized
Expects ct to have clean carries
Sourcepub fn unchecked_ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn unchecked_ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the base 2 logarithm of the number, rounded down.
See Self::ilog2_parallelized for an example
Expects ct to have clean carries
Sourcepub fn smart_trailing_zeros_parallelized<T>(
&self,
ct: &mut T,
) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_trailing_zeros_parallelized<T>(
&self,
ct: &mut T,
) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_trailing_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_trailing_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_leading_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_leading_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_leading_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_leading_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Sourcepub fn smart_ilog2_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn smart_ilog2_parallelized<T>(&self, ct: &mut T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the base 2 logarithm of the number, rounded down.
See Self::ilog2_parallelized for an example
Sourcepub fn smart_checked_ilog2_parallelized<T>(
&self,
ct: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn smart_checked_ilog2_parallelized<T>(
&self,
ct: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the base 2 logarithm of the number, rounded down.
See Self::checked_ilog2_parallelized for an example
Also returns a BooleanBlock, encrypting true (1) if the result is valid (input is > 0), otherwise 0.
Sourcepub fn trailing_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn trailing_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of trailing zeros in the binary representation of ct
The returned Ciphertexts has a variable size i.e. It contains just the minimum number of block needed to represent the maximum possible number of bits.
This is a default function, it will internally clone the ciphertext if it has non propagated carries, and it will output a ciphertext without any carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = -4i8;
let ct1 = cks.encrypt_signed(msg);
let n = sks.trailing_zeros_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.trailing_zeros());
Sourcepub fn trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of trailing ones in the binary representation of ct
The returned Ciphertexts has a variable size i.e. It contains just the minimum number of block needed to represent the maximum possible number of bits.
This is a default function, it will internally clone the ciphertext if it has non propagated carries, and it will output a ciphertext without any carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = -4i8;
let ct1 = cks.encrypt_signed(msg);
let n = sks.trailing_ones_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.trailing_ones());
Sourcepub fn leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of leading zeros in the binary representation of ct
The returned Ciphertexts has a variable size i.e. It contains just the minimum number of block needed to represent the maximum possible number of bits.
This is a default function, it will internally clone the ciphertext if it has non propagated carries, and it will output a ciphertext without any carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = -4i8;
let ct1 = cks.encrypt_signed(msg);
let n = sks.leading_zeros_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.leading_zeros());
Sourcepub fn leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the number of leading ones in the binary representation of ct
The returned Ciphertexts has a variable size i.e. It contains just the minimum number of block needed to represent the maximum possible number of bits.
This is a default function, it will internally clone the ciphertext if it has non propagated carries, and it will output a ciphertext without any carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = -4i8;
let ct1 = cks.encrypt_signed(msg);
let n = sks.leading_ones_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.leading_ones());
Sourcepub fn ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
pub fn ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertextwhere
T: IntegerRadixCiphertext,
Returns the base 2 logarithm of the number, rounded down.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = 5i8;
let ct1 = cks.encrypt_signed(msg);
let n = sks.ilog2_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.ilog2());
Sourcepub fn checked_ilog2_parallelized<T>(
&self,
ct: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn checked_ilog2_parallelized<T>(
&self,
ct: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the base 2 logarithm of the number, rounded down.
Also returns a BooleanBlock, encrypting true (1) if the result is valid (input is > 0), otherwise 0.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, num_blocks);
let msg = 5i8;
let ct1 = cks.encrypt_signed(msg);
let (n, is_oks) = sks.checked_ilog2_parallelized(&ct1);
// Decrypt:
let n: u32 = cks.decrypt(&n);
assert_eq!(n, msg.ilog2());
let is_ok = cks.decrypt_bool(&is_oks);
assert!(is_ok);
Source§impl ServerKey
impl ServerKey
Sourcepub fn reverse_bits_parallelized<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
pub fn reverse_bits_parallelized<T>(&self, ct: &T) -> Twhere
T: IntegerRadixCiphertext,
Reverse the bits of the integer
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
let num_blocks = 4;
// Generate the client key and the server key:
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 0b10110100_u8;
let ct = cks.encrypt(msg);
// Compute homomorphically an addition:
let ct_res = sks.reverse_bits_parallelized(&ct);
// Decrypt:
let res: u8 = cks.decrypt(&ct_res);
assert_eq!(msg.reverse_bits(), res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &[BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
pub fn unchecked_boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &[BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
Computes the dot product between encrypted booleans and clear values
n_blocks
number of blocks in the resulting ciphertext
§Panic
- Panics if
boolean_blocks
andclears
do not have the same lengths - Panics if
boolean_blocks
orclears
is empty
Sourcepub fn smart_boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &mut [BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
pub fn smart_boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &mut [BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
Computes the dot product between encrypted booleans and clear values
n_blocks
number of blocks in the resulting ciphertext
§Panic
- Panics if
boolean_blocks
andclears
do not have the same lengths - Panics if
boolean_blocks
orclears
is empty
Sourcepub fn boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &[BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
pub fn boolean_scalar_dot_prod_parallelized<Clear, T>(
&self,
boolean_blocks: &[BooleanBlock],
clears: &[Clear],
n_blocks: u32,
) -> Twhere
Clear: Numeric + DecomposableInto<u64> + CastInto<usize> + CastFrom<u128> + Mul<Clear, Output = Clear> + AddAssign<Clear> + OverflowingAdd<Clear, Output = Clear>,
T: IntegerRadixCiphertext,
Computes the dot product between encrypted booleans and clear values
n_blocks
number of blocks in the resulting ciphertext
§Panic
- Panics if
boolean_blocks
andclears
do not have the same lengths - Panics if
boolean_blocks
orclears
is empty
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_scalar_bitslice_parallelized<B, R>(
&self,
ctxt: &RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn unchecked_scalar_bitslice_parallelized<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks
.unchecked_scalar_bitslice_parallelized(&ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn unchecked_scalar_bitslice_assign_parallelized<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn unchecked_scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.unchecked_scalar_bitslice_assign_parallelized(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn scalar_bitslice_parallelized<B, R>(
&self,
ctxt: &RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn scalar_bitslice_parallelized<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let ct = cks.encrypt(msg);
let ct_res = sks
.scalar_bitslice_parallelized(&ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn scalar_bitslice_assign_parallelized<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.scalar_bitslice_assign_parallelized(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn smart_scalar_bitslice_parallelized<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<RadixCiphertext, InvalidRangeError>
pub fn smart_scalar_bitslice_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is returned as a new ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
let ct_res = sks
.smart_scalar_bitslice_parallelized(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct_res);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Sourcepub fn smart_scalar_bitslice_assign_parallelized<B, R>(
&self,
ctxt: &mut RadixCiphertext,
range: R,
) -> Result<(), InvalidRangeError>
pub fn smart_scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
Extract a slice of bits from a ciphertext.
The result is assigned to the input ciphertext. This function is more efficient if the range starts on a block boundary.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg: u64 = 225;
let start_bit = 3;
let end_bit = 6;
// Encrypt the message:
let mut ct = cks.encrypt(msg);
sks.smart_scalar_bitslice_assign(&mut ct, start_bit..end_bit)
.unwrap();
// Decrypt:
let clear = cks.decrypt(&ct);
assert_eq!((msg % (1 << end_bit)) >> start_bit, clear);
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_all_eq_slices_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_all_eq_slices_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares two slices containing ciphertexts and returns an encryption of true
if all
pairs are equal, otherwise, returns an encryption of false
.
- If slices do not have the same length, false is returned
- If at least one pair (
lhs[i]
,rhs[i]
) do not have the same number of blocks, false is returned
Sourcepub fn smart_all_eq_slices_parallelized<T>(
&self,
lhs: &mut [T],
rhs: &mut [T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_all_eq_slices_parallelized<T>(
&self,
lhs: &mut [T],
rhs: &mut [T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares two slices containing ciphertexts and returns an encryption of true
if all
pairs are equal, otherwise, returns an encryption of false
.
- If slices do not have the same length, false is returned
- If at least one pair (
lhs[i]
,rhs[i]
) do not have the same number of blocks, false is returned
Sourcepub fn all_eq_slices_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn all_eq_slices_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Compares two slices containing ciphertexts and returns an encryption of true
if all
pairs are equal, otherwise, returns an encryption of false
.
- If slices do not have the same length, false is returned
- If at least one pair (
lhs[i]
,rhs[i]
) do not have the same number of blocks, false is returned
Sourcepub fn unchecked_contains_sub_slice_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_contains_sub_slice_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns a boolean ciphertext encrypting true
if lhs
contains rhs
, false
otherwise
Sourcepub fn smart_contains_sub_slice_parallelized<T>(
&self,
lhs: &mut [T],
rhs: &mut [T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_contains_sub_slice_parallelized<T>(
&self,
lhs: &mut [T],
rhs: &mut [T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns a boolean ciphertext encrypting true
if lhs
contains rhs
, false
otherwise
Sourcepub fn contains_sub_slice_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn contains_sub_slice_parallelized<T>(
&self,
lhs: &[T],
rhs: &[T],
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns a boolean ciphertext encrypting true
if lhs
contains rhs
, false
otherwise
Source§impl ServerKey
impl ServerKey
Sourcepub fn unchecked_match_value_parallelized<Clear>(
&self,
ct: &RadixCiphertext,
matches: &MatchValues<Clear>,
) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_match_value_parallelized<Clear>( &self, ct: &RadixCiphertext, matches: &MatchValues<Clear>, ) -> (RadixCiphertext, BooleanBlock)
match
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
Returns a boolean block that encrypts true
if the input ct
matched one of the possible inputs
Sourcepub fn smart_match_value_parallelized<Clear>(
&self,
ct: &mut RadixCiphertext,
matches: &MatchValues<Clear>,
) -> (RadixCiphertext, BooleanBlock)
pub fn smart_match_value_parallelized<Clear>( &self, ct: &mut RadixCiphertext, matches: &MatchValues<Clear>, ) -> (RadixCiphertext, BooleanBlock)
match
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
Returns a boolean block that encrypts true
if the input ct
matched one of the possible inputs
Sourcepub fn match_value_parallelized<Clear>(
&self,
ct: &RadixCiphertext,
matches: &MatchValues<Clear>,
) -> (RadixCiphertext, BooleanBlock)
pub fn match_value_parallelized<Clear>( &self, ct: &RadixCiphertext, matches: &MatchValues<Clear>, ) -> (RadixCiphertext, BooleanBlock)
match
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
Returns a boolean block that encrypts true
if the input ct
matched one of the possible inputs
Sourcepub fn unchecked_match_value_or_parallelized<Clear>(
&self,
ct: &RadixCiphertext,
matches: &MatchValues<Clear>,
or_value: Clear,
) -> RadixCiphertext
pub fn unchecked_match_value_or_parallelized<Clear>( &self, ct: &RadixCiphertext, matches: &MatchValues<Clear>, or_value: Clear, ) -> RadixCiphertext
match
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
If none of the input matched the ct
then, ct
will encrypt the
value given to or_value
Sourcepub fn smart_match_value_or_parallelized<Clear>(
&self,
ct: &mut RadixCiphertext,
matches: &MatchValues<Clear>,
or_value: Clear,
) -> RadixCiphertext
pub fn smart_match_value_or_parallelized<Clear>( &self, ct: &mut RadixCiphertext, matches: &MatchValues<Clear>, or_value: Clear, ) -> RadixCiphertext
map
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
If none of the input matched the ct
then, ct
will encrypt the
value given to or_value
Sourcepub fn match_value_or_parallelized<Clear>(
&self,
ct: &RadixCiphertext,
matches: &MatchValues<Clear>,
or_value: Clear,
) -> RadixCiphertext
pub fn match_value_or_parallelized<Clear>( &self, ct: &RadixCiphertext, matches: &MatchValues<Clear>, or_value: Clear, ) -> RadixCiphertext
match
an input value to an output value
-
Input values are not required to span all possible values that
ct
could hold. -
The output radix has a number of blocks that depends on the maximum possible output value from the
MatchValues
If none of the input matched the ct
then, ct
will encrypt the
value given to or_value
Sourcepub fn unchecked_contains_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn unchecked_contains_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encrypted true
if the encrypted value
is found in the encrypted slice
Sourcepub fn smart_contains_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn smart_contains_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encrypted true
if the encrypted value
is found in the encrypted slice
Sourcepub fn contains_parallelized<T>(&self, cts: &[T], value: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
pub fn contains_parallelized<T>(&self, cts: &[T], value: &T) -> BooleanBlockwhere
T: IntegerRadixCiphertext,
Returns an encrypted true
if the encrypted value
is found in the encrypted slice
Sourcepub fn unchecked_contains_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> BooleanBlock
pub fn unchecked_contains_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> BooleanBlock
Returns an encrypted true
if the clear value
is found in the encrypted slice
Sourcepub fn smart_contains_clear_parallelized<T, Clear>(
&self,
cts: &mut [T],
clear: Clear,
) -> BooleanBlock
pub fn smart_contains_clear_parallelized<T, Clear>( &self, cts: &mut [T], clear: Clear, ) -> BooleanBlock
Returns an encrypted true
if the clear value
is found in the encrypted slice
Sourcepub fn contains_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> BooleanBlock
pub fn contains_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> BooleanBlock
Returns an encrypted true
if the clear value
is found in the encrypted slice
Sourcepub fn unchecked_is_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> BooleanBlock
pub fn unchecked_is_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> BooleanBlock
Returns an encrypted true
if the encrypted value
is found in the clear slice
Sourcepub fn smart_is_in_clears_parallelized<T, Clear>(
&self,
ct: &mut T,
clears: &[Clear],
) -> BooleanBlock
pub fn smart_is_in_clears_parallelized<T, Clear>( &self, ct: &mut T, clears: &[Clear], ) -> BooleanBlock
Returns an encrypted true
if the encrypted value
is found in the clear slice
Sourcepub fn is_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> BooleanBlock
pub fn is_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> BooleanBlock
Returns an encrypted true
if the encrypted value
is found in the clear slice
Sourcepub fn unchecked_index_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_index_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the encrypted value
in the clear slice
also returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::unchecked_first_index_in_clears_parallelized)
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn smart_index_in_clears_parallelized<T, Clear>(
&self,
ct: &mut T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn smart_index_in_clears_parallelized<T, Clear>( &self, ct: &mut T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the encrypted value
in the clear slice
also returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::smart_first_index_in_clears_parallelized)
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn index_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn index_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the encrypted value
in the clear slice
also returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::index_in_clears_parallelized)
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn unchecked_first_index_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_first_index_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of encrypted value
in the clear
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn smart_first_index_in_clears_parallelized<T, Clear>(
&self,
ct: &mut T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn smart_first_index_in_clears_parallelized<T, Clear>( &self, ct: &mut T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of encrypted value
in the clear
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn first_index_in_clears_parallelized<T, Clear>(
&self,
ct: &T,
clears: &[Clear],
) -> (RadixCiphertext, BooleanBlock)
pub fn first_index_in_clears_parallelized<T, Clear>( &self, ct: &T, clears: &[Clear], ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of encrypted value
in the clear
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn unchecked_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn unchecked_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the of encrypted value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::unchecked_first_index_of_parallelized)
- If the encrypted value is not in the encrypted slice, the returned index is 0
Sourcepub fn smart_index_of_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn smart_index_of_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the of encrypted value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::smart_first_index_of_parallelized)
- If the encrypted value is not in the encrypted slice, the returned index is 0
Sourcepub fn index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the of encrypted value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::first_index_of_parallelized)
- If the encrypted value is not in the encrypted slice, the returned index is 0
Sourcepub fn unchecked_index_of_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_index_of_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the of clear value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::unchecked_first_index_of_clear_parallelized)
- If the clear value is not in the encrypted slice, the returned index is 0
Sourcepub fn smart_index_of_clear_parallelized<T, Clear>(
&self,
cts: &mut [T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn smart_index_of_clear_parallelized<T, Clear>( &self, cts: &mut [T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the of clear value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::smart_first_index_of_clear_parallelized)
- If the clear value is not in the encrypted slice, the returned index is 0
Sourcepub fn index_of_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn index_of_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the of clear value
in the ciphertext slice
also, it returns an encrypted boolean that is true
if the encrypted value was found.
§Notes
- clear values in the slice must be unique (otherwise use Self::first_index_of_clear_parallelized)
- If the clear value is not in the encrypted slice, the returned index is 0
Sourcepub fn unchecked_first_index_of_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn unchecked_first_index_of_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of clear value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the clear value is not in the clear slice, the returned index is 0
Sourcepub fn smart_first_index_of_clear_parallelized<T, Clear>(
&self,
cts: &mut [T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn smart_first_index_of_clear_parallelized<T, Clear>( &self, cts: &mut [T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of clear value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the clear value is not in the clear slice, the returned index is 0
Sourcepub fn first_index_of_clear_parallelized<T, Clear>(
&self,
cts: &[T],
clear: Clear,
) -> (RadixCiphertext, BooleanBlock)
pub fn first_index_of_clear_parallelized<T, Clear>( &self, cts: &[T], clear: Clear, ) -> (RadixCiphertext, BooleanBlock)
Returns the encrypted index of the first occurrence of clear value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the clear value is not in the clear slice, the returned index is 0
Sourcepub fn unchecked_first_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn unchecked_first_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the first occurrence of encrypted value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn smart_first_index_of_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn smart_first_index_of_parallelized<T>(
&self,
cts: &mut [T],
value: &mut T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the first occurrence of encrypted value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Sourcepub fn first_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
pub fn first_index_of_parallelized<T>(
&self,
cts: &[T],
value: &T,
) -> (RadixCiphertext, BooleanBlock)where
T: IntegerRadixCiphertext,
Returns the encrypted index of the first occurrence of encrypted value
in the ciphertext
slice also, it returns an encrypted boolean that is true
if the encrypted value was
found.
§Notes
- If the encrypted value is not in the clear slice, the returned index is 0
Source§impl ServerKey
impl ServerKey
Sourcepub fn propagate_parallelized<T>(
&self,
ctxt: &mut T,
index: usize,
) -> Ciphertextwhere
T: IntegerRadixCiphertext,
pub fn propagate_parallelized<T>(
&self,
ctxt: &mut T,
index: usize,
) -> Ciphertextwhere
T: IntegerRadixCiphertext,
Propagate the carry of the ‘index’ block to the next one.
§Example
use tfhe::integer::{gen_keys_radix, IntegerCiphertext};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 7u64;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);
// Compute homomorphically an addition:
let mut ct_res = sks.unchecked_add(&ct1, &ct2);
let carry = sks.propagate_parallelized(&mut ct_res, 0);
// Decrypt one block:
let res: u64 = cks.decrypt_one_block(&ct_res.blocks()[1]);
assert_eq!(3, res);
Sourcepub fn partial_propagate_parallelized<T>(
&self,
ctxt: &mut T,
start_index: usize,
)where
T: IntegerRadixCiphertext,
pub fn partial_propagate_parallelized<T>(
&self,
ctxt: &mut T,
start_index: usize,
)where
T: IntegerRadixCiphertext,
Propagates carries starting from start_index.
Does nothing if start_index >= ctxt.len() or ctxt is empty
Sourcepub fn full_propagate_parallelized<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
pub fn full_propagate_parallelized<T>(&self, ctxt: &mut T)where
T: IntegerRadixCiphertext,
Propagate all the carries.
§Example
use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key and the server key:
let num_blocks = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, num_blocks);
let msg = 10u64;
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);
// Compute homomorphically an addition:
let mut ct_res = sks.unchecked_add(&ct1, &ct2);
sks.full_propagate_parallelized(&mut ct_res);
// Decrypt:
let res: u64 = cks.decrypt(&ct_res);
assert_eq!(msg + msg, res);
Source§impl ServerKey
impl ServerKey
Sourcepub fn new_radix_server_key<C>(cks: C) -> Self
pub fn new_radix_server_key<C>(cks: C) -> Self
Generates a server key.
§Example
use tfhe::integer::{ClientKey, ServerKey};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// Generate the client key:
let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128);
// Generate the server key:
let sks = ServerKey::new_radix_server_key(cks);
pub fn new_crt_server_key<C>(cks: C) -> Self
Sourcepub fn new_radix_server_key_from_shortint(key: ServerKey) -> Self
pub fn new_radix_server_key_from_shortint(key: ServerKey) -> Self
Creates a ServerKey destined to be used with
RadixCiphertext
from an already generated
shortint::ServerKey.
§Example
use tfhe::integer::{ClientKey, ServerKey};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::shortint::ServerKey as ShortintServerKey;
// Generate the client key:
let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128);
// Generate the shortint server key:
let shortint_sks = ShortintServerKey::new(cks.as_ref());
// Generate the server key:
let sks = ServerKey::new_radix_server_key_from_shortint(shortint_sks);
Sourcepub fn new_crt_server_key_from_shortint(key: ServerKey) -> Self
pub fn new_crt_server_key_from_shortint(key: ServerKey) -> Self
Creates a ServerKey destined to be used with
CrtCiphertext
from an already generated
shortint::ServerKey.
§Example
use tfhe::integer::{ClientKey, ServerKey};
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
use tfhe::shortint::ServerKey as ShortintServerKey;
// Generate the client key:
let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128);
// Generate the shortint server key:
let shortint_sks = ShortintServerKey::new(cks.as_ref());
// Generate the server key:
let sks = ServerKey::new_crt_server_key_from_shortint(shortint_sks);
Sourcepub fn into_raw_parts(self) -> ServerKey
pub fn into_raw_parts(self) -> ServerKey
Deconstruct a ServerKey
into its constituents.
Sourcepub fn from_raw_parts(key: ServerKey) -> Self
pub fn from_raw_parts(key: ServerKey) -> Self
Construct a ServerKey
from its constituents.
pub fn deterministic_pbs_execution(&self) -> bool
pub fn set_deterministic_pbs_execution( &mut self, new_deterministic_execution: bool, )
pub fn message_modulus(&self) -> MessageModulus
pub fn carry_modulus(&self) -> CarryModulus
Sourcepub fn num_blocks_to_represent_unsigned_value<Clear>(
&self,
clear: Clear,
) -> usizewhere
Clear: UnsignedInteger,
pub fn num_blocks_to_represent_unsigned_value<Clear>(
&self,
clear: Clear,
) -> usizewhere
Clear: UnsignedInteger,
Returns how many blocks a radix ciphertext should have to be able to represent the given unsigned integer
Trait Implementations§
Source§impl Deprecable for ServerKey
impl Deprecable for ServerKey
Source§impl<'de> Deserialize<'de> for ServerKey
impl<'de> Deserialize<'de> for ServerKey
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl ParameterSetConformant for ServerKey
impl ParameterSetConformant for ServerKey
type ParameterSet = AtomicPatternParameters
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool
Source§impl<Scalar> ServerKeyDefaultCMux<&BaseRadixCiphertext<Ciphertext>, Scalar> for ServerKeywhere
Scalar: DecomposableInto<u64>,
impl<Scalar> ServerKeyDefaultCMux<&BaseRadixCiphertext<Ciphertext>, Scalar> for ServerKeywhere
Scalar: DecomposableInto<u64>,
Source§fn if_then_else_parallelized(
&self,
condition: &BooleanBlock,
true_ct: &RadixCiphertext,
false_value: Scalar,
) -> Self::Output
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_ct: &RadixCiphertext, false_value: Scalar, ) -> Self::Output
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_ct or a clear false_value depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_ct.
- If condition == 0, the returned ciphertext will encrypt the same value as false_value.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as true_ct, it won’t exactly be true_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::integer::prelude::*;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let a = 126i8;
let b = -55i8;
let ct_a = cks.encrypt_signed(a);
let condition = sks.scalar_lt_parallelized(&ct_a, 66);
let ct_res = sks.if_then_else_parallelized(&condition, &ct_a, b);
// Decrypt:
let dec: i8 = cks.decrypt_signed(&ct_res);
assert_eq!(if a < 66 { a } else { b }, dec);
assert_ne!(ct_a, ct_res);
type Output = BaseRadixCiphertext<Ciphertext>
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl<Scalar> ServerKeyDefaultCMux<&BaseSignedRadixCiphertext<Ciphertext>, Scalar> for ServerKeywhere
Scalar: DecomposableInto<u64>,
impl<Scalar> ServerKeyDefaultCMux<&BaseSignedRadixCiphertext<Ciphertext>, Scalar> for ServerKeywhere
Scalar: DecomposableInto<u64>,
type Output = BaseSignedRadixCiphertext<Ciphertext>
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_ct: &SignedRadixCiphertext, false_value: Scalar, ) -> Self::Output
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl ServerKeyDefaultCMux<&BooleanBlock, &BooleanBlock> for ServerKey
impl ServerKeyDefaultCMux<&BooleanBlock, &BooleanBlock> for ServerKey
Source§fn if_then_else_parallelized(
&self,
condition: &BooleanBlock,
true_ct: &BooleanBlock,
false_ct: &BooleanBlock,
) -> Self::Output
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_ct: &BooleanBlock, false_ct: &BooleanBlock, ) -> Self::Output
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_ct or false_ct depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_ct.
- If condition == 0, the returned ciphertext will encrypt the same value as false_ct.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as either true_ct or false_ct, it won’t exactly be true_ct or false_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::integer::prelude::*;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
for cond in [true, false] {
for a in [true, false] {
for b in [true, false] {
let condition = cks.encrypt_bool(cond);
let ct_a = cks.encrypt_bool(a);
let ct_b = cks.encrypt_bool(b);
let ct_res = sks.if_then_else_parallelized(&condition, &ct_a, &ct_b);
// Decrypt:
let dec = cks.decrypt_bool(&ct_res);
assert_eq!(if cond { a } else { b }, dec);
assert_ne!(ct_a, ct_res);
assert_ne!(ct_b, ct_res);
}
}
}
type Output = BooleanBlock
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl<T> ServerKeyDefaultCMux<&T, &T> for ServerKeywhere
T: IntegerRadixCiphertext,
impl<T> ServerKeyDefaultCMux<&T, &T> for ServerKeywhere
T: IntegerRadixCiphertext,
Source§fn if_then_else_parallelized(
&self,
condition: &BooleanBlock,
true_ct: &T,
false_ct: &T,
) -> Self::Output
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_ct: &T, false_ct: &T, ) -> Self::Output
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_ct or false_ct depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_ct.
- If condition == 0, the returned ciphertext will encrypt the same value as false_ct.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as either true_ct or false_ct, it won’t exactly be true_ct or false_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::integer::prelude::*;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let a = 128u8;
let b = 55u8;
let ct_a = cks.encrypt(a);
let ct_b = cks.encrypt(b);
let condition = sks.scalar_ge_parallelized(&ct_a, 66);
let ct_res = sks.if_then_else_parallelized(&condition, &ct_a, &ct_b);
// Decrypt:
let dec: u8 = cks.decrypt(&ct_res);
assert_eq!(if a >= 66 { a } else { b }, dec);
assert_ne!(ct_a, ct_res);
assert_ne!(ct_b, ct_res);
type Output = T
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseRadixCiphertext<Ciphertext>> for ServerKeywhere
Scalar: DecomposableInto<u64>,
impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseRadixCiphertext<Ciphertext>> for ServerKeywhere
Scalar: DecomposableInto<u64>,
Source§fn if_then_else_parallelized(
&self,
condition: &BooleanBlock,
true_value: Scalar,
false_ct: &RadixCiphertext,
) -> Self::Output
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_value: Scalar, false_ct: &RadixCiphertext, ) -> Self::Output
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_value or a false_ct depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_value.
- If condition == 0, the returned ciphertext will encrypt the same value as false_ct.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as true_ct, it won’t exactly be true_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::integer::prelude::*;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let a = 126u8;
let b = 55u8;
let ct_b = cks.encrypt(b);
let condition = sks.scalar_lt_parallelized(&ct_b, 66);
let ct_res = sks.if_then_else_parallelized(&condition, a, &ct_b);
// Decrypt:
let dec: u8 = cks.decrypt(&ct_res);
assert_eq!(if b < 66 { a } else { b }, dec);
assert_ne!(ct_b, ct_res);
type Output = BaseRadixCiphertext<Ciphertext>
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseSignedRadixCiphertext<Ciphertext>> for ServerKeywhere
Scalar: DecomposableInto<u64>,
impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseSignedRadixCiphertext<Ciphertext>> for ServerKeywhere
Scalar: DecomposableInto<u64>,
Source§fn if_then_else_parallelized(
&self,
condition: &BooleanBlock,
true_value: Scalar,
false_ct: &SignedRadixCiphertext,
) -> Self::Output
fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_value: Scalar, false_ct: &SignedRadixCiphertext, ) -> Self::Output
FHE “if then else” selection.
Returns a new ciphertext that encrypts the same value as either true_value or a false_ct depending on the value of condition:
- If condition == 1, the returned ciphertext will encrypt the same value as true_value.
- If condition == 0, the returned ciphertext will encrypt the same value as false_ct.
To ensure correct results, condition must encrypt either 0 or 1 (e.g result from a comparison).
Note that while the returned ciphertext encrypts the same value as true_ct, it won’t exactly be true_ct.
use tfhe::integer::gen_keys_radix;
use tfhe::integer::prelude::*;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
// We have 4 * 2 = 8 bits of message
let size = 4;
let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, size);
let a = 126i8;
let b = -55i8;
let ct_b = cks.encrypt_signed(b);
let condition = sks.scalar_lt_parallelized(&ct_b, 66);
let ct_res = sks.if_then_else_parallelized(&condition, a, &ct_b);
// Decrypt:
let dec: i8 = cks.decrypt_signed(&ct_res);
assert_eq!(if b < 66 { a } else { b }, dec);
assert_ne!(ct_b, ct_res);
type Output = BaseSignedRadixCiphertext<Ciphertext>
fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output
fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output
Source§impl Unversionize for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl Unversionize for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
Source§fn unversionize(
versioned: Self::VersionedOwned,
) -> Result<Self, UnversionizeError>
fn unversionize( versioned: Self::VersionedOwned, ) -> Result<Self, UnversionizeError>
Source§impl UnversionizeVec for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl UnversionizeVec for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
fn unversionize_vec( versioned: Self::VersionedVec, ) -> Result<Vec<Self>, UnversionizeError>
Source§impl Versionize for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl Versionize for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
Source§type Versioned<'vers> = <ServerKeyVersions as VersionsDispatch<ServerKey>>::Ref<'vers>
type Versioned<'vers> = <ServerKeyVersions as VersionsDispatch<ServerKey>>::Ref<'vers>
Source§fn versionize(&self) -> Self::Versioned<'_>
fn versionize(&self) -> Self::Versioned<'_>
Source§impl VersionizeOwned for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl VersionizeOwned for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
type VersionedOwned = <ServerKeyVersions as VersionsDispatch<ServerKey>>::Owned
Source§fn versionize_owned(self) -> Self::VersionedOwned
fn versionize_owned(self) -> Self::VersionedOwned
Source§impl VersionizeSlice for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl VersionizeSlice for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
type VersionedSlice<'vers> = Vec<<ServerKey as Versionize>::Versioned<'vers>>
fn versionize_slice(slice: &[Self]) -> Self::VersionedSlice<'_>
Source§impl VersionizeVec for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
impl VersionizeVec for ServerKeywhere
ServerKeyVersions: VersionsDispatch<Self>,
type VersionedVec = Vec<<ServerKey as VersionizeOwned>::VersionedOwned>
fn versionize_vec(vec: Vec<Self>) -> Self::VersionedVec
Auto Trait Implementations§
impl Freeze for ServerKey
impl RefUnwindSafe for ServerKey
impl Send for ServerKey
impl Sync for ServerKey
impl Unpin for ServerKey
impl UnwindSafe for ServerKey
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more