Struct ServerKey

Source
pub struct ServerKey { /* private fields */ }
Available on crate feature 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

Source

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));
Source

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

Source

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)));
Source

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

Source

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);
Source

pub fn smart_crt_add_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, )

Source

pub fn is_crt_add_possible( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> Result<(), CheckError>

Source

pub fn unchecked_crt_add_assign( &self, ct_left: &mut CrtCiphertext, ct_right: &CrtCiphertext, )

Source

pub fn unchecked_crt_add( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext

Source§

impl ServerKey

Source

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);
Source

pub fn unchecked_crt_mul( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext

Source

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);
Source

pub fn smart_crt_mul( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext

Source§

impl ServerKey

Source

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);
Source

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.

Source

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);
Source

pub fn smart_crt_neg(&self, ctxt: &mut CrtCiphertext) -> CrtCiphertext

Source

pub fn is_crt_neg_possible( &self, ctxt: &CrtCiphertext, ) -> Result<(), CheckError>

Source§

impl ServerKey

Source

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);
Source

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.

Source

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();
Source

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);
Source

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.

Source

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);
Source

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

Source

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);
Source

pub fn unchecked_crt_scalar_mul_assign( &self, ctxt: &mut CrtCiphertext, scalar: u64, )

Source

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();
Source

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);
Source

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.

Source

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);
Source

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);
Source

pub fn is_crt_small_scalar_mul_possible( &self, ctxt: &CrtCiphertext, scalar: u64, ) -> Result<(), CheckError>

Source§

impl ServerKey

Source

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);
Source

pub fn unchecked_crt_scalar_sub_assign( &self, ct: &mut CrtCiphertext, scalar: u64, )

Source

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);
Source

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);
Source

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);
Source

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);
Source

pub fn smart_crt_scalar_sub_assign(&self, ct: &mut CrtCiphertext, scalar: u64)

Source§

impl ServerKey

Source

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);
Source

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);
Source

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);
Source

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);
Source

pub fn is_crt_sub_possible( &self, ctxt_left: &CrtCiphertext, ctxt_right: &CrtCiphertext, ) -> Result<(), CheckError>

Source§

impl ServerKey

Source

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);
Source

pub fn pbs_crt_compliant_function_assign<F>( &self, ct1: &mut CrtCiphertext, f: F, )
where F: Fn(u64) -> u64,

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);
Source

pub fn pbs_crt_compliant_function<F>( &self, ct1: &CrtCiphertext, f: F, ) -> CrtCiphertext
where F: Fn(u64) -> u64,

Source§

impl ServerKey

Source

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);
Source

pub fn unchecked_crt_add_parallelized( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext

Source

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);
Source

pub fn smart_crt_add_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext

Source§

impl ServerKey

Source

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);
Source

pub fn unchecked_crt_mul_parallelized( &self, ct_left: &CrtCiphertext, ct_right: &CrtCiphertext, ) -> CrtCiphertext

Source

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);
Source

pub fn smart_crt_mul_parallelized( &self, ct_left: &mut CrtCiphertext, ct_right: &mut CrtCiphertext, ) -> CrtCiphertext

Source§

impl ServerKey

Source

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);
Source

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.

Source

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);
Source

pub fn smart_crt_neg_parallelized( &self, ctxt: &mut CrtCiphertext, ) -> CrtCiphertext

Source§

impl ServerKey

Source

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);
Source

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.

Source

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);
Source

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.

Source

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);
Source

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

Source

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);
Source

pub fn unchecked_crt_scalar_mul_assign_parallelized( &self, ctxt: &mut CrtCiphertext, scalar: u64, )

Source

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);
Source

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.

Source

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);
Source

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

Source

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);
Source

pub fn unchecked_crt_scalar_sub_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )

Source

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);
Source

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);
Source

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);
Source

pub fn smart_crt_scalar_sub_assign_parallelized( &self, ct: &mut CrtCiphertext, scalar: u64, )

Source§

impl ServerKey

Source

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);
Source

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);
Source

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);
Source

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

Source

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);
Source

pub fn pbs_crt_compliant_function_assign_parallelized<F>( &self, ct1: &mut CrtCiphertext, f: F, )
where F: Fn(u64) -> u64,

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);
Source

pub fn pbs_crt_compliant_function_parallelized<F>( &self, ct1: &CrtCiphertext, f: F, ) -> CrtCiphertext
where F: Fn(u64) -> u64,

Source§

impl ServerKey

Source

pub fn unchecked_add<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn unchecked_add_assign<T>(&self, ct_left: &mut T, ct_right: &T)

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);
Source

pub fn is_add_possible<T>( &self, ct_left: &T, ct_right: &T, ) -> Result<(), CheckError>

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();
Source

pub fn checked_add<T>(&self, ct_left: &T, ct_right: &T) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_add_assign<T>( &self, ct_left: &mut T, ct_right: &T, ) -> Result<(), CheckError>

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);
Source

pub fn smart_add<T>(&self, ct_left: &mut T, ct_right: &mut T) -> T

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);
Source

pub fn smart_add_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)

Source

pub fn unchecked_signed_overflowing_add( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source§

impl ServerKey

Source

pub fn unchecked_bitand<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn unchecked_bitand_assign<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn is_functional_bivariate_pbs_possible<T>( &self, ct_left: &T, ct_right: &T, ) -> Result<(), CheckError>

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();
Source

pub fn checked_bitand<T>( &self, ct_left: &T, ct_right: &T, ) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_bitand_assign<T>( &self, ct_left: &mut T, ct_right: &T, ) -> Result<(), CheckError>

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);
Source

pub fn smart_bitand<T>(&self, ct_left: &mut T, ct_right: &mut T) -> T

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);
Source

pub fn smart_bitand_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)

Source

pub fn unchecked_bitor<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn unchecked_bitor_assign<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn checked_bitor<T>( &self, ct_left: &T, ct_right: &T, ) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_bitor_assign<T>( &self, ct_left: &mut T, ct_right: &T, ) -> Result<(), CheckError>

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);
Source

pub fn smart_bitor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> T

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);
Source

pub fn smart_bitor_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)

Source

pub fn unchecked_bitxor<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn unchecked_bitxor_assign<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn checked_bitxor<T>( &self, ct_left: &T, ct_right: &T, ) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_bitxor_assign<T>( &self, ct_left: &mut T, ct_right: &T, ) -> Result<(), CheckError>

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);
Source

pub fn smart_bitxor<T>(&self, ct_left: &mut T, ct_right: &mut T) -> T

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);
Source

pub fn smart_bitxor_assign<T>(&self, ct_left: &mut T, ct_right: &mut T)

Source

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));
Source

pub fn boolean_bitand_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)

Source

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);
Source

pub fn boolean_bitor_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)

Source

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)));
Source

pub fn boolean_bitxor_assign(&self, lhs: &mut BooleanBlock, rhs: &BooleanBlock)

Source

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);
Source

pub fn boolean_bitnot_assign(&self, boolean_block: &mut BooleanBlock)

Source§

impl ServerKey

Source

pub fn unchecked_eq<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

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);
Source

pub fn unchecked_ne<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_gt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

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);
Source

pub fn unchecked_ge<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

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);
Source

pub fn unchecked_lt<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

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);
Source

pub fn unchecked_le<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

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);
Source

pub fn unchecked_max<T>(&self, lhs: &T, rhs: &T) -> T

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));
Source

pub fn unchecked_min<T>(&self, lhs: &T, rhs: &T) -> T

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));
Source

pub fn smart_eq<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

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);
Source

pub fn smart_ne<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_gt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

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);
Source

pub fn smart_ge<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

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);
Source

pub fn smart_lt<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

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);
Source

pub fn smart_le<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

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);
Source

pub fn smart_max<T>(&self, lhs: &mut T, rhs: &mut T) -> T

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));
Source

pub fn smart_min<T>(&self, lhs: &mut T, rhs: &mut T) -> T

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

Source

pub fn unchecked_block_mul_assign<T>( &self, ct_left: &mut T, ct_right: &Ciphertext, index: usize, )

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);
Source

pub fn unchecked_block_mul<T>( &self, ct1: &T, ct2: &Ciphertext, index: usize, ) -> T

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);
Source

pub fn smart_block_mul<T>( &self, ct1: &mut T, ct2: &mut Ciphertext, index: usize, ) -> T

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);
Source

pub fn smart_block_mul_assign<T>( &self, ct1: &mut T, ct2: &mut Ciphertext, index: usize, )

Source

pub fn unchecked_mul_assign<T>(&self, ct1: &mut T, ct2: &T)

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);
Source

pub fn unchecked_mul<T>(&self, ct1: &T, ct2: &T) -> T

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.

Source

pub fn smart_mul_assign<T>(&self, ct1: &mut T, ct2: &mut T)

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);
Source

pub fn smart_mul<T>(&self, ct1: &mut T, ct2: &mut T) -> T

Computes homomorphically a multiplication between two ciphertexts encrypting integer values.

The result is returned as a new ciphertext.

Source§

impl ServerKey

Source

pub fn unchecked_neg<T>(&self, ctxt: &T) -> T

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);
Source

pub fn unchecked_neg_assign<T>(&self, ctxt: &mut T)

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.

Source

pub fn is_neg_possible<T>(&self, ctxt: &T) -> Result<(), CheckError>

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();
Source

pub fn checked_neg<T>(&self, ctxt: &T) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_neg_assign<T>(&self, ctxt: &mut T) -> Result<(), CheckError>

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));
Source

pub fn smart_neg<T>(&self, ctxt: &mut T) -> T

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);
Source

pub fn smart_neg_assign<T>(&self, ctxt: &mut T)

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

Source

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);
Source

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.

Source

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();
Source

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);
Source

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.

Source

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);
Source

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

Source

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);
Source

pub fn unchecked_small_scalar_mul_assign( &self, ctxt: &mut RadixCiphertext, scalar: u64, )

Source

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());
Source

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);
    }
}
Source

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);
Source

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);
Source

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);
Source

pub fn blockshift<T>(&self, ctxt: &T, shift: usize) -> T

§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);
Source

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);
Source

pub fn smart_scalar_mul_assign<T>(&self, ctxt: &mut RadixCiphertext, scalar: T)

Source§

impl ServerKey

Source

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);
Source

pub fn unchecked_scalar_sub_assign<T, Scalar>(&self, ct: &mut T, scalar: Scalar)

Source

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();
Source

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);
Source

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);
Source

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);
Source

pub fn smart_scalar_sub_assign<T, Scalar>( &self, ct: &mut RadixCiphertext, scalar: Scalar, )

Source§

impl ServerKey

Source

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);
Source

pub fn blockshift_right_assign(&self, ctxt: &mut RadixCiphertext, shift: usize)

Source

pub fn unchecked_scalar_right_shift<T>( &self, ct: &RadixCiphertext, shift: T, ) -> RadixCiphertext
where T: Rem<T, Output = T> + CastFrom<u64>, u64: CastFrom<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 = 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);
Source

pub fn unchecked_scalar_right_shift_assign<T>( &self, ct: &mut RadixCiphertext, shift: T, )
where T: Rem<T, Output = T> + CastFrom<u64>, u64: CastFrom<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);
Source

pub fn unchecked_scalar_left_shift<T>( &self, ct_left: &RadixCiphertext, shift: T, ) -> RadixCiphertext
where T: Rem<T, Output = T> + CastFrom<u64>, u64: CastFrom<T>,

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);
Source

pub fn unchecked_scalar_left_shift_assign<T>( &self, ct: &mut RadixCiphertext, shift: T, )
where T: Rem<T, Output = T> + CastFrom<u64>, u64: CastFrom<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

Source

pub fn scalar_blockslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

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);
Source

pub fn unchecked_scalar_bitslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn unchecked_scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn scalar_bitslice<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn smart_scalar_bitslice<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn smart_scalar_bitslice_assign<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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

Source

pub fn unchecked_sub<T>(&self, ctxt_left: &T, ctxt_right: &T) -> T

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);
Source

pub fn unchecked_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &T)

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);
Source

pub fn is_sub_possible<T>( &self, ctxt_left: &T, ctxt_right: &T, ) -> Result<(), CheckError>

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();
Source

pub fn checked_sub<T>( &self, ctxt_left: &T, ctxt_right: &T, ) -> Result<T, CheckError>

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);
    }
}
Source

pub fn checked_sub_assign<T>( &self, ct_left: &mut T, ct_right: &T, ) -> Result<(), CheckError>

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);
Source

pub fn smart_sub<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T) -> T

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);
Source

pub fn smart_sub_assign<T>(&self, ctxt_left: &mut T, ctxt_right: &mut T)

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);
Source

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);
Source

pub fn unchecked_unsigned_overflowing_sub( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)

Source

pub fn unchecked_signed_overflowing_sub( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source

pub fn signed_overflowing_sub( &self, ctxt_left: &SignedRadixCiphertext, ctxt_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source§

impl ServerKey

Source

pub fn unchecked_is_even<T>(&self, ct: &T) -> BooleanBlock

Returns an encryption of true if the value is even

ct is not required to have clean carries

Source

pub fn unchecked_is_odd<T>(&self, ct: &T) -> BooleanBlock

Returns an encryption of true if the value is odd ct is not required to have clean carries

Source

pub fn smart_is_even_parallelized<T>(&self, ct: &mut T) -> BooleanBlock

Returns an encryption of true if the value is even

Source

pub fn smart_is_odd_parallelized<T>(&self, ct: &mut T) -> BooleanBlock

Returns an encryption of true if the value is odd

Source

pub fn is_even_parallelized<T>(&self, ct: &T) -> BooleanBlock

Returns an encryption of true if the value is even

Source

pub fn is_odd_parallelized<T>(&self, ct: &T) -> BooleanBlock

Returns an encryption of true if the value is odd

Source§

impl ServerKey

Source

pub fn create_trivial_zero_assign_radix<T>(&self, ctxt: &mut T)

Source

pub fn create_trivial_zero_radix<T>(&self, num_blocks: usize) -> T

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);
Source

pub fn create_trivial_boolean_block(&self, value: bool) -> BooleanBlock

Source

pub fn create_trivial_max_radix<T>(&self, num_blocks: usize) -> T

Source

pub fn create_trivial_min_radix<T>(&self, num_blocks: usize) -> T

Source

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);
Source

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
 );
Source

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
 );
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

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);
Source

pub fn propagate<T>(&self, ctxt: &mut T, index: usize)

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);
Source

pub fn full_propagate<T>(&self, ctxt: &mut T)

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

Source

pub fn unchecked_abs_parallelized<T>(&self, ct: &T) -> T

Source

pub fn smart_abs_parallelized<T>(&self, ct: &mut T) -> T

Source

pub fn abs_parallelized<T>(&self, ct: &T) -> T

Source§

impl ServerKey

Source

pub fn unchecked_add_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

Source

pub fn unchecked_add_assign_parallelized<T>(&self, lhs: &mut T, rhs: &T)

Source

pub fn smart_add_parallelized<T>(&self, ct_left: &mut T, ct_right: &mut T) -> T

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);
Source

pub fn smart_add_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, )

Source

pub fn add_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn add_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn overflowing_add_parallelized<T>( &self, ct_left: &T, ct_right: &T, ) -> (T, BooleanBlock)

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);
Source

pub fn overflowing_add_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &T, ) -> BooleanBlock

Source

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);
Source

pub fn unsigned_overflowing_add_assign_parallelized( &self, ct_left: &mut RadixCiphertext, ct_right: &RadixCiphertext, ) -> BooleanBlock

Source

pub fn signed_overflowing_add_parallelized( &self, ct_left: &SignedRadixCiphertext, ct_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source

pub fn unchecked_signed_overflowing_add_parallelized( &self, ct_left: &SignedRadixCiphertext, ct_right: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source

pub fn add_assign_with_carry_parallelized<T>( &self, lhs: &mut T, rhs: &T, input_carry: Option<&BooleanBlock>, )

Does lhs += (rhs + carry)

Source

pub fn overflowing_add_assign_with_carry<T>( &self, lhs: &mut T, rhs: &T, input_carry: Option<&BooleanBlock>, ) -> BooleanBlock

Does lhs += (rhs + carry)

Returns a boolean block that encrypts true if overflow happened

Source§

impl ServerKey

Source

pub fn unchecked_bitand_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

Source

pub fn unchecked_bitand_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &T, )

Source

pub fn smart_bitand_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, ) -> T

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);
Source

pub fn smart_bitand_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, )

Source

pub fn bitand_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn bitand_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn unchecked_bitor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

Source

pub fn unchecked_bitor_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &T, )

Source

pub fn smart_bitor_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, ) -> T

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);
Source

pub fn smart_bitor_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, )

Source

pub fn bitor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn bitor_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn unchecked_bitxor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

Source

pub fn unchecked_bitxor_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &T, )

Source

pub fn smart_bitxor_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, ) -> T

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);
Source

pub fn smart_bitxor_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &mut T, )

Source

pub fn bitxor_parallelized<T>(&self, ct_left: &T, ct_right: &T) -> T

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);
Source

pub fn bitxor_assign_parallelized<T>(&self, ct_left: &mut T, ct_right: &T)

Source

pub fn bitnot<T>(&self, ct: &T) -> T

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));
Source

pub fn bitnot_assign<T>(&self, ct: &mut T)

Source§

impl ServerKey

Source

pub fn unchecked_block_rotate_right<T>( &self, ct: &T, amount: &RadixCiphertext, ) -> T

Source

pub fn unchecked_block_rotate_left<T>( &self, ct: &T, amount: &RadixCiphertext, ) -> T

Source

pub fn unchecked_block_shift_right<T>( &self, ct: &T, amount: &RadixCiphertext, ) -> T

Source

pub fn unchecked_block_shift_left<T>( &self, ct: &T, amount: &RadixCiphertext, ) -> T

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

pub fn smart_block_rotate_right<T>( &self, ct: &mut T, amount: &RadixCiphertext, ) -> T

Source

pub fn smart_block_rotate_left<T>( &self, ct: &mut T, amount: &RadixCiphertext, ) -> T

Source

pub fn smart_block_shift_right<T>( &self, ct: &mut T, amount: &RadixCiphertext, ) -> T

Source

pub fn smart_block_shift_left<T>( &self, ct: &mut T, amount: &RadixCiphertext, ) -> T

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

pub fn block_rotate_right<T>(&self, ct: &T, amount: &RadixCiphertext) -> T

Source

pub fn block_rotate_left<T>(&self, ct: &T, amount: &RadixCiphertext) -> T

Source

pub fn block_shift_right<T>(&self, ct: &T, amount: &RadixCiphertext) -> T

Source

pub fn block_shift_left<T>(&self, ct: &T, amount: &RadixCiphertext) -> T

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

Source

pub fn unchecked_if_then_else_parallelized<T>( &self, condition: &BooleanBlock, true_ct: &T, false_ct: &T, ) -> T

Source

pub fn scalar_cmux_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T

Source

pub fn scalar_select_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T

Source

pub fn scalar_if_then_else_parallelized<Scalar, T>( &self, condition: &BooleanBlock, true_value: Scalar, false_value: Scalar, n_blocks: usize, ) -> T

Source

pub fn unchecked_cmux<T>( &self, condition: &BooleanBlock, true_ct: &T, false_ct: &T, ) -> T

Source

pub fn cmux_parallelized<T>( &self, condition: &BooleanBlock, true_ct: &T, false_ct: &T, ) -> T

Encrypted CMUX.

It is another name for Self::if_then_else_parallelized

Source

pub fn smart_if_then_else_parallelized<T>( &self, condition: &mut BooleanBlock, true_ct: &mut T, false_ct: &mut T, ) -> T

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);
Source

pub fn smart_cmux_parallelized<T>( &self, condition: &mut BooleanBlock, true_ct: &mut T, false_ct: &mut T, ) -> T

Encrypted CMUX.

It is another name for Self::smart_if_then_else_parallelized

Source§

impl ServerKey

Source

pub fn unchecked_eq_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_ne_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_gt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_ge_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_lt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_le_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn unchecked_max_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

Source

pub fn unchecked_min_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

Source

pub fn smart_eq_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_ne_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_gt_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_ge_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_lt_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_le_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> BooleanBlock

Source

pub fn smart_max_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> T

Source

pub fn smart_min_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> T

Source

pub fn eq_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn ne_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn gt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn ge_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn lt_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn le_parallelized<T>(&self, lhs: &T, rhs: &T) -> BooleanBlock

Source

pub fn max_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

Source

pub fn min_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

Source§

impl ServerKey

Source

pub fn unchecked_div_rem_parallelized<T>( &self, numerator: &T, divisor: &T, ) -> (T, T)

Source

pub fn unchecked_div_rem_floor_parallelized( &self, numerator: &SignedRadixCiphertext, divisor: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, SignedRadixCiphertext)

Source

pub fn div_rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> (T, T)

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);
Source

pub fn smart_div_rem_parallelized<T>( &self, numerator: &mut T, divisor: &mut T, ) -> (T, T)

Source

pub fn unchecked_div_assign_parallelized<T>( &self, numerator: &mut T, divisor: &T, )

Source

pub fn unchecked_div_parallelized<T>(&self, numerator: &T, divisor: &T) -> T

Source

pub fn smart_div_assign_parallelized<T>( &self, numerator: &mut T, divisor: &mut T, )

Source

pub fn smart_div_parallelized<T>(&self, numerator: &mut T, divisor: &mut T) -> T

Source

pub fn div_assign_parallelized<T>(&self, numerator: &mut T, divisor: &T)

Source

pub fn div_parallelized<T>(&self, numerator: &T, divisor: &T) -> T

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);
Source

pub fn unchecked_rem_assign_parallelized<T>( &self, numerator: &mut T, divisor: &T, )

Source

pub fn unchecked_rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> T

Source

pub fn smart_rem_assign_parallelized<T>( &self, numerator: &mut T, divisor: &mut T, )

Source

pub fn smart_rem_parallelized<T>(&self, numerator: &mut T, divisor: &mut T) -> T

Source

pub fn rem_assign_parallelized<T>(&self, numerator: &mut T, divisor: &T)

Source

pub fn rem_parallelized<T>(&self, numerator: &T, divisor: &T) -> T

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);
Source

pub fn checked_div_rem_parallelized<T>( &self, numerator: &T, divisor: &T, ) -> (T, T, BooleanBlock)

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);
Source

pub fn checked_div_parallelized<T>( &self, numerator: &T, divisor: &T, ) -> (T, BooleanBlock)

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);
Source

pub fn checked_rem_parallelized<T>( &self, numerator: &T, divisor: &T, ) -> (T, BooleanBlock)

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

Source

pub fn switch_modulus_and_compress_parallelized( &self, ct: &RadixCiphertext, ) -> CompressedModulusSwitchedRadixCiphertext

Compresses a ciphertext to have a smaller serialization size

See CompressedModulusSwitchedRadixCiphertext for usage

Source

pub fn decompress_parallelized( &self, compressed_ct: &CompressedModulusSwitchedRadixCiphertext, ) -> RadixCiphertext

Decompresses a compressed ciphertext This operation costs a PBS

See CompressedModulusSwitchedRadixCiphertext for usage

Source

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

Source

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

Source

pub fn unchecked_block_mul_assign_parallelized<T>( &self, ct_left: &mut T, ct_right: &Ciphertext, index: usize, )

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);
Source

pub fn unchecked_block_mul_parallelized<T>( &self, ct1: &T, ct2: &Ciphertext, index: usize, ) -> T

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);
Source

pub fn smart_block_mul_parallelized<T>( &self, ct1: &mut T, ct2: &mut Ciphertext, index: usize, ) -> T

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);
Source

pub fn block_mul_parallelized<T>( &self, ct1: &T, ct2: &Ciphertext, index: usize, ) -> T

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);
Source

pub fn block_mul_assign_parallelized<T>( &self, ct1: &mut T, ct2: &Ciphertext, index: usize, )

Source

pub fn smart_block_mul_assign_parallelized<T>( &self, ct1: &mut T, ct2: &mut Ciphertext, index: usize, )

Source

pub fn unchecked_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &T)

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);
Source

pub fn unchecked_mul_parallelized<T>(&self, lhs: &T, rhs: &T) -> T

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
Source

pub fn smart_mul_assign_parallelized<T>(&self, lhs: &mut T, rhs: &mut T)

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);
Source

pub fn smart_mul_parallelized<T>(&self, lhs: &mut T, rhs: &mut T) -> T

Computes homomorphically a multiplication between two ciphertexts encrypting integer values.

The result is returned as a new ciphertext.

§Warning
  • Multithreaded
Source

pub fn mul_parallelized<T>(&self, ct1: &T, ct2: &T) -> T

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);
Source

pub fn mul_assign_parallelized<T>(&self, ct1: &mut T, ct2: &T)

Source

pub fn unchecked_unsigned_overflowing_mul_parallelized( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)

Source

pub fn unchecked_unsigned_overflowing_mul_assign_parallelized( &self, lhs: &mut RadixCiphertext, rhs: &RadixCiphertext, ) -> BooleanBlock

Source

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);
Source

pub fn unsigned_overflowing_mul_assign_parallelized( &self, ct1: &mut RadixCiphertext, ct2: &RadixCiphertext, ) -> BooleanBlock

Source

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

Source

pub fn smart_neg_parallelized<T>(&self, ctxt: &mut T) -> T

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);
Source

pub fn neg_parallelized<T>(&self, ctxt: &T) -> T

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

Source

pub fn unchecked_rotate_right_parallelized<T>( &self, ct: &T, n: &RadixCiphertext, ) -> T

Source

pub fn unchecked_rotate_right_assign_parallelized<T>( &self, ct: &mut T, n: &RadixCiphertext, )

Source

pub fn smart_rotate_right_assign_parallelized<T>( &self, ct: &mut T, n: &mut RadixCiphertext, )

Source

pub fn smart_rotate_right_parallelized<T>( &self, ct: &mut T, rotate: &mut RadixCiphertext, ) -> T

Source

pub fn rotate_right_assign_parallelized<T>( &self, ct: &mut T, rotate: &RadixCiphertext, )

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);
Source

pub fn rotate_right_parallelized<T>( &self, ct: &T, rotate: &RadixCiphertext, ) -> T

Source

pub fn unchecked_rotate_left_parallelized<T>( &self, ct_left: &T, n: &RadixCiphertext, ) -> T

Source

pub fn unchecked_rotate_left_assign_parallelized<T>( &self, ct: &mut T, n: &RadixCiphertext, )

Source

pub fn smart_rotate_left_assign_parallelized<T>( &self, ct: &mut T, n: &mut RadixCiphertext, )

Source

pub fn smart_rotate_left_parallelized<T>( &self, ct: &mut T, rotate: &mut RadixCiphertext, ) -> T

Source

pub fn rotate_left_assign_parallelized<T>( &self, ct: &mut T, rotate: &RadixCiphertext, )

Source

pub fn rotate_left_parallelized<T>(&self, ct: &T, rotate: &RadixCiphertext) -> 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.

§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

Source

pub fn overflowing_scalar_add_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, ) -> BooleanBlock

Source

pub fn overflowing_scalar_add_parallelized<T, Scalar>( &self, lhs: &T, scalar: Scalar, ) -> (T, BooleanBlock)

Source

pub fn unsigned_overflowing_scalar_add_assign_parallelized<Scalar>( &self, lhs: &mut RadixCiphertext, scalar: Scalar, ) -> BooleanBlock

Source

pub fn unsigned_overflowing_scalar_add_parallelized<Scalar>( &self, lhs: &RadixCiphertext, scalar: Scalar, ) -> (RadixCiphertext, BooleanBlock)

Source

pub fn signed_overflowing_scalar_add_assign_parallelized<Scalar>( &self, lhs: &mut SignedRadixCiphertext, scalar: Scalar, ) -> BooleanBlock

Source

pub fn signed_overflowing_scalar_add_parallelized<Scalar>( &self, lhs: &SignedRadixCiphertext, scalar: Scalar, ) -> (SignedRadixCiphertext, BooleanBlock)

Source

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);
Source

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);
Source

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);
Source

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

Source

pub fn unchecked_scalar_bitand_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T

Source

pub fn unchecked_scalar_bitand_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )

Source

pub fn smart_scalar_bitand_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T

Source

pub fn smart_scalar_bitand_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )

Source

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);
Source

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);
Source

pub fn unchecked_scalar_bitor_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T

Source

pub fn unchecked_scalar_bitor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )

Source

pub fn smart_scalar_bitor_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T

Source

pub fn smart_scalar_bitor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )

Source

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);
Source

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);
Source

pub fn unchecked_scalar_bitxor_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T

Source

pub fn unchecked_scalar_bitxor_assign_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, )

Source

pub fn smart_scalar_bitxor_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T

Source

pub fn smart_scalar_bitxor_assign_parallelized<T, Scalar>( &self, lhs: &mut RadixCiphertext, rhs: Scalar, )

Source

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);
Source

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

Source

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);
Source

pub fn unchecked_scalar_ne_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_eq_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_eq_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_ne_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_ne_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn unchecked_scalar_gt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn unchecked_scalar_ge_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn unchecked_scalar_lt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn unchecked_scalar_le_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn unchecked_scalar_max_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T

Source

pub fn unchecked_scalar_min_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> T

Source

pub fn smart_scalar_gt_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_ge_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_lt_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_le_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn smart_scalar_max_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T

Source

pub fn smart_scalar_min_parallelized<T, Scalar>( &self, lhs: &mut T, rhs: Scalar, ) -> T

Source

pub fn scalar_gt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_ge_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_lt_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_le_parallelized<T, Scalar>( &self, lhs: &T, rhs: Scalar, ) -> BooleanBlock

Source

pub fn scalar_max_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T

Source

pub fn scalar_min_parallelized<T, Scalar>(&self, lhs: &T, rhs: Scalar) -> T

Source§

impl ServerKey

Source

pub fn unchecked_scalar_div_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> RadixCiphertext
where T: Reciprocable,

Source

pub fn unchecked_signed_scalar_div_parallelized<T>( &self, numerator: &SignedRadixCiphertext, divisor: T, ) -> SignedRadixCiphertext
where T: SignedReciprocable, <<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,

§Note

This division rounds (truncates) the quotient towards zero

Source

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
Source

pub fn unchecked_signed_scalar_rem_parallelized<T>( &self, numerator: &SignedRadixCiphertext, divisor: T, ) -> SignedRadixCiphertext
where T: SignedReciprocable + ScalarMultiplier, <<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,

§Note
Source

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
Source

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
Source

pub fn signed_scalar_div_parallelized<T>( &self, numerator: &SignedRadixCiphertext, divisor: T, ) -> SignedRadixCiphertext
where 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
Source

pub fn signed_scalar_rem_parallelized<T>( &self, numerator: &SignedRadixCiphertext, divisor: T, ) -> SignedRadixCiphertext
where 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
Source

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.

Source

pub fn unchecked_signed_scalar_div_floor_parallelized<T>( &self, numerator: &SignedRadixCiphertext, divisor: T, ) -> SignedRadixCiphertext
where T: SignedReciprocable, <<T as SignedReciprocable>::Unsigned as Reciprocable>::DoublePrecision: Send,

§Note

This division rounds the quotient towards minus infinity

Source

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

Source

pub fn unchecked_scalar_div_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> (RadixCiphertext, RadixCiphertext)

Source

pub fn unchecked_scalar_rem_parallelized<T>( &self, numerator: &RadixCiphertext, divisor: T, ) -> RadixCiphertext

Source

pub fn smart_scalar_div_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )

Source

pub fn smart_scalar_rem_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )

Source

pub fn smart_scalar_div_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> RadixCiphertext

Source

pub fn smart_scalar_rem_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> RadixCiphertext

Source

pub fn smart_scalar_div_rem_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, ) -> (RadixCiphertext, RadixCiphertext)

Source

pub fn scalar_div_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )

Source

pub fn scalar_rem_assign_parallelized<T>( &self, numerator: &mut RadixCiphertext, divisor: T, )

Source

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);
Source

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);
Source

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

Source

pub fn unchecked_scalar_mul_parallelized<T, Scalar>( &self, ct: &T, scalar: Scalar, ) -> T

Source

pub fn unchecked_scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )

Source

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);
Source

pub fn smart_scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )

Source

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);
Source

pub fn scalar_mul_assign_parallelized<T, Scalar>( &self, lhs: &mut T, scalar: Scalar, )

Source§

impl ServerKey

Source

pub fn smart_scalar_rotate_right_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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.

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);
Source

pub fn smart_scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn scalar_rotate_right_parallelized<T, Scalar>( &self, ct_right: &T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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 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);
Source

pub fn scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn unchecked_scalar_rotate_right_parallelized<T, Scalar>( &self, ct: &T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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 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);
Source

pub fn unchecked_scalar_rotate_right_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn smart_scalar_rotate_left_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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.

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);
Source

pub fn smart_scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn scalar_rotate_left_parallelized<T, Scalar>( &self, ct_left: &T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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 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);
Source

pub fn scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn unchecked_scalar_rotate_left_parallelized<T, Scalar>( &self, ct: &T, n: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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 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);
Source

pub fn unchecked_scalar_rotate_left_assign_parallelized<T, Scalar>( &self, ct: &mut T, n: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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

Source

pub fn unchecked_scalar_right_shift_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

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);
Source

pub fn unchecked_scalar_right_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn unchecked_scalar_right_shift_arithmetic_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

Source

pub fn unchecked_scalar_right_shift_arithmetic_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

Source

pub fn unchecked_scalar_right_shift_logical_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

Source

pub fn scalar_right_shift_parallelized<T, Scalar>( &self, ct: &T, shift: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<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 = 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);
Source

pub fn scalar_right_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn unchecked_scalar_left_shift_parallelized<T, Scalar>( &self, ct_left: &T, shift: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

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);
Source

pub fn unchecked_scalar_left_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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);
Source

pub fn scalar_left_shift_parallelized<T, Scalar>( &self, ct_left: &T, shift: Scalar, ) -> T
where T: IntegerRadixCiphertext, u64: CastFrom<Scalar>,

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);
Source

pub fn scalar_left_shift_assign_parallelized<T, Scalar>( &self, ct: &mut T, shift: Scalar, )
where T: IntegerRadixCiphertext, u64: CastFrom<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

Source

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);
Source

pub fn smart_scalar_sub_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )

Source

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);
Source

pub fn scalar_sub_assign_parallelized<T, Scalar>( &self, ct: &mut T, scalar: Scalar, )

Source

pub fn unchecked_left_scalar_sub<Scalar, T>(&self, scalar: Scalar, rhs: &T) -> T

Source

pub fn is_left_scalar_sub_possible<Scalar, T>( &self, scalar: Scalar, rhs: &T, ) -> Result<(), CheckError>

Source

pub fn smart_left_scalar_sub_parallelized<Scalar, T>( &self, scalar: Scalar, rhs: &mut T, ) -> T

Source

pub fn left_scalar_sub_parallelized<Scalar, T>( &self, scalar: Scalar, rhs: &T, ) -> T

Source

pub fn unsigned_overflowing_scalar_sub_assign_parallelized<T>( &self, lhs: &mut RadixCiphertext, scalar: T, ) -> BooleanBlock
where T: UnsignedNumeric + DecomposableInto<u8> + Not<Output = T>,

Source

pub fn unsigned_overflowing_scalar_sub_parallelized<T>( &self, lhs: &RadixCiphertext, scalar: T, ) -> (RadixCiphertext, BooleanBlock)
where T: UnsignedNumeric + DecomposableInto<u8> + Not<Output = T>,

Source

pub fn signed_overflowing_scalar_sub_assign_parallelized<Scalar>( &self, lhs: &mut SignedRadixCiphertext, scalar: Scalar, ) -> BooleanBlock
where Scalar: SignedNumeric + DecomposableInto<u8> + Not<Output = Scalar>,

Source

pub fn signed_overflowing_scalar_sub_parallelized<Scalar>( &self, lhs: &SignedRadixCiphertext, scalar: Scalar, ) -> (SignedRadixCiphertext, BooleanBlock)
where Scalar: SignedNumeric + DecomposableInto<u8> + Not<Output = Scalar>,

Source§

impl ServerKey

Source

pub fn unchecked_right_shift_parallelized<T>( &self, ct_left: &T, shift: &RadixCiphertext, ) -> T

Source

pub fn unchecked_right_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &RadixCiphertext, )

Source

pub fn smart_right_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &mut RadixCiphertext, )

Source

pub fn smart_right_shift_parallelized<T>( &self, ct: &mut T, shift: &mut RadixCiphertext, ) -> T

Source

pub fn right_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &RadixCiphertext, )

Source

pub fn right_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> T

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);
Source

pub fn unchecked_left_shift_parallelized<T>( &self, ct_left: &T, shift: &RadixCiphertext, ) -> T

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
Source

pub fn unchecked_left_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &RadixCiphertext, )

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
Source

pub fn smart_left_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &mut RadixCiphertext, )

Source

pub fn smart_left_shift_parallelized<T>( &self, ct: &mut T, shift: &mut RadixCiphertext, ) -> T

Source

pub fn left_shift_assign_parallelized<T>( &self, ct: &mut T, shift: &RadixCiphertext, )

Source

pub fn left_shift_parallelized<T>(&self, ct: &T, shift: &RadixCiphertext) -> T

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

Source

pub fn smart_sub_parallelized<T>( &self, ctxt_left: &mut T, ctxt_right: &mut T, ) -> T

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);
Source

pub fn smart_sub_assign_parallelized<T>( &self, ctxt_left: &mut T, ctxt_right: &mut T, )

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);
Source

pub fn sub_parallelized<T>(&self, ctxt_left: &T, ctxt_right: &T) -> T

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);
Source

pub fn sub_assign_parallelized<T>(&self, ctxt_left: &mut T, ctxt_right: &T)

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);
Source

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);
Source

pub fn unchecked_unsigned_overflowing_sub_parallelized( &self, lhs: &RadixCiphertext, rhs: &RadixCiphertext, ) -> (RadixCiphertext, BooleanBlock)

Source

pub fn unchecked_signed_overflowing_sub_parallelized( &self, lhs: &SignedRadixCiphertext, rhs: &SignedRadixCiphertext, ) -> (SignedRadixCiphertext, BooleanBlock)

Source

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

Source

pub fn unchecked_sum_ciphertexts_vec_parallelized<T>( &self, ciphertexts: Vec<T>, ) -> Option<T>

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

Source

pub fn unchecked_sum_ciphertexts_parallelized<'a, T, C>( &self, ciphertexts: C, ) -> Option<T>
where C: IntoIterator<Item = &'a T>, T: IntegerRadixCiphertext + 'a,

Source

pub fn sum_ciphertexts_parallelized<'a, T, C>( &self, ciphertexts: C, ) -> Option<T>
where C: IntoIterator<Item = &'a T>, T: IntegerRadixCiphertext + 'a,

Computes the sum of the ciphertexts in parallel.

  • Returns None if ciphertexts is empty

See Self::unchecked_sum_ciphertexts_parallelized for constraints

Source

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

Source

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
Source

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.

See Self::unchecked_sum_ciphertexts_vec_parallelized

Source

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

Source

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

Source

pub fn unchecked_count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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)
Source

pub fn unchecked_count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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)
Source

pub fn smart_count_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

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)
Source

pub fn smart_count_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

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

pub fn count_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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)
Source

pub fn count_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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

Source

pub fn unchecked_trailing_zeros_parallelized<T>( &self, ct: &T, ) -> RadixCiphertext

See Self::trailing_zeros_parallelized

Expects ct to have clean carries

Source

pub fn unchecked_trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

See Self::trailing_ones_parallelized

Expects ct to have clean carries

Source

pub fn unchecked_leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertext

See Self::leading_zeros_parallelized

Expects ct to have clean carries

Source

pub fn unchecked_leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

See Self::leading_ones_parallelized

Expects ct to have clean carries

Source

pub fn unchecked_ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertext

Returns the base 2 logarithm of the number, rounded down.

See Self::ilog2_parallelized for an example

Expects ct to have clean carries

Source

pub fn smart_trailing_zeros_parallelized<T>( &self, ct: &mut T, ) -> RadixCiphertext

Source

pub fn smart_trailing_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

Source

pub fn smart_leading_zeros_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

Source

pub fn smart_leading_ones_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

Source

pub fn smart_ilog2_parallelized<T>(&self, ct: &mut T) -> RadixCiphertext

Returns the base 2 logarithm of the number, rounded down.

See Self::ilog2_parallelized for an example

Source

pub fn smart_checked_ilog2_parallelized<T>( &self, ct: &mut T, ) -> (RadixCiphertext, BooleanBlock)

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.

Source

pub fn trailing_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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());
Source

pub fn trailing_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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());
Source

pub fn leading_zeros_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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());
Source

pub fn leading_ones_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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());
Source

pub fn ilog2_parallelized<T>(&self, ct: &T) -> RadixCiphertext

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());
Source

pub fn checked_ilog2_parallelized<T>( &self, ct: &T, ) -> (RadixCiphertext, BooleanBlock)

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

Source

pub fn reverse_bits_parallelized<T>(&self, ct: &T) -> T

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

Source

pub fn unchecked_boolean_scalar_dot_prod_parallelized<Clear, T>( &self, boolean_blocks: &[BooleanBlock], clears: &[Clear], n_blocks: u32, ) -> T
where 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 and clears do not have the same lengths
  • Panics if boolean_blocks or clears is empty
Source

pub fn smart_boolean_scalar_dot_prod_parallelized<Clear, T>( &self, boolean_blocks: &mut [BooleanBlock], clears: &[Clear], n_blocks: u32, ) -> T
where 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 and clears do not have the same lengths
  • Panics if boolean_blocks or clears is empty
Source

pub fn boolean_scalar_dot_prod_parallelized<Clear, T>( &self, boolean_blocks: &[BooleanBlock], clears: &[Clear], n_blocks: u32, ) -> T
where 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 and clears do not have the same lengths
  • Panics if boolean_blocks or clears is empty
Source§

impl ServerKey

Source

pub fn unchecked_scalar_bitslice_parallelized<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn unchecked_scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn scalar_bitslice_parallelized<B, R>( &self, ctxt: &RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn smart_scalar_bitslice_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<RadixCiphertext, InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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);
Source

pub fn smart_scalar_bitslice_assign_parallelized<B, R>( &self, ctxt: &mut RadixCiphertext, range: R, ) -> Result<(), InvalidRangeError>
where R: RangeBounds<B>, B: CastFrom<usize> + CastInto<usize> + Copy,

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

Source

pub fn unchecked_all_eq_slices_parallelized<T>( &self, lhs: &[T], rhs: &[T], ) -> BooleanBlock

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
Source

pub fn smart_all_eq_slices_parallelized<T>( &self, lhs: &mut [T], rhs: &mut [T], ) -> BooleanBlock

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
Source

pub fn all_eq_slices_parallelized<T>( &self, lhs: &[T], rhs: &[T], ) -> BooleanBlock

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
Source

pub fn unchecked_contains_sub_slice_parallelized<T>( &self, lhs: &[T], rhs: &[T], ) -> BooleanBlock

Returns a boolean ciphertext encrypting true if lhs contains rhs, false otherwise

Source

pub fn smart_contains_sub_slice_parallelized<T>( &self, lhs: &mut [T], rhs: &mut [T], ) -> BooleanBlock

Returns a boolean ciphertext encrypting true if lhs contains rhs, false otherwise

Source

pub fn contains_sub_slice_parallelized<T>( &self, lhs: &[T], rhs: &[T], ) -> BooleanBlock

Returns a boolean ciphertext encrypting true if lhs contains rhs, false otherwise

Source§

impl ServerKey

Source

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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

pub fn unchecked_contains_parallelized<T>( &self, cts: &[T], value: &T, ) -> BooleanBlock

Returns an encrypted true if the encrypted value is found in the encrypted slice

Source

pub fn smart_contains_parallelized<T>( &self, cts: &mut [T], value: &mut T, ) -> BooleanBlock

Returns an encrypted true if the encrypted value is found in the encrypted slice

Source

pub fn contains_parallelized<T>(&self, cts: &[T], value: &T) -> BooleanBlock

Returns an encrypted true if the encrypted value is found in the encrypted slice

Source

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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

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
Source

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
Source

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
Source

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
Source

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
Source

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
Source

pub fn unchecked_index_of_parallelized<T>( &self, cts: &[T], value: &T, ) -> (RadixCiphertext, BooleanBlock)

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
Source

pub fn smart_index_of_parallelized<T>( &self, cts: &mut [T], value: &mut T, ) -> (RadixCiphertext, BooleanBlock)

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
Source

pub fn index_of_parallelized<T>( &self, cts: &[T], value: &T, ) -> (RadixCiphertext, BooleanBlock)

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
Source

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
Source

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
Source

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
Source

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
Source

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
Source

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
Source

pub fn unchecked_first_index_of_parallelized<T>( &self, cts: &[T], value: &T, ) -> (RadixCiphertext, BooleanBlock)

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

pub fn smart_first_index_of_parallelized<T>( &self, cts: &mut [T], value: &mut T, ) -> (RadixCiphertext, BooleanBlock)

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

pub fn first_index_of_parallelized<T>( &self, cts: &[T], value: &T, ) -> (RadixCiphertext, BooleanBlock)

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

Source

pub fn propagate_parallelized<T>( &self, ctxt: &mut T, index: usize, ) -> Ciphertext

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);
Source

pub fn partial_propagate_parallelized<T>( &self, ctxt: &mut T, start_index: usize, )

Propagates carries starting from start_index.

Does nothing if start_index >= ctxt.len() or ctxt is empty

Source

pub fn full_propagate_parallelized<T>(&self, ctxt: &mut T)

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

Source

pub fn new_radix_server_key<C>(cks: C) -> Self
where C: AsRef<ClientKey>,

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);
Source

pub fn new_crt_server_key<C>(cks: C) -> Self
where C: AsRef<ClientKey>,

Source

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);
Source

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);
Source

pub fn into_raw_parts(self) -> ServerKey

Deconstruct a ServerKey into its constituents.

Source

pub fn from_raw_parts(key: ServerKey) -> Self

Construct a ServerKey from its constituents.

Source

pub fn deterministic_pbs_execution(&self) -> bool

Source

pub fn set_deterministic_pbs_execution( &mut self, new_deterministic_execution: bool, )

Source

pub fn message_modulus(&self) -> MessageModulus

Source

pub fn carry_modulus(&self) -> CarryModulus

Source

pub fn num_blocks_to_represent_unsigned_value<Clear>( &self, clear: Clear, ) -> usize
where Clear: UnsignedInteger,

Returns how many blocks a radix ciphertext should have to be able to represent the given unsigned integer

Trait Implementations§

Source§

impl AsRef<GenericServerKey<AtomicPatternServerKey>> for ServerKey

Source§

fn as_ref(&self) -> &ServerKey

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<ServerKey> for ServerKey

Source§

fn as_ref(&self) -> &ServerKey

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Clone for ServerKey

Source§

fn clone(&self) -> ServerKey

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Deprecable for ServerKey

Source§

const TYPE_NAME: &'static str = "ServerKey"

Source§

const MIN_SUPPORTED_APP_VERSION: &'static str = "TFHE-rs v0.10"

Source§

fn error() -> DeprecatedVersionError

Source§

impl<'de> Deserialize<'de> for ServerKey

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl From<ServerKey> for ServerKey

Source§

fn from(key: ServerKey) -> Self

Converts to this type from the input type.
Source§

impl ParameterSetConformant for ServerKey

Source§

impl Serialize for ServerKey

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<Scalar> ServerKeyDefaultCMux<&BaseRadixCiphertext<Ciphertext>, Scalar> for ServerKey
where Scalar: DecomposableInto<u64>,

Source§

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);
Source§

type Output = BaseRadixCiphertext<Ciphertext>

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl<Scalar> ServerKeyDefaultCMux<&BaseSignedRadixCiphertext<Ciphertext>, Scalar> for ServerKey
where Scalar: DecomposableInto<u64>,

Source§

type Output = BaseSignedRadixCiphertext<Ciphertext>

Source§

fn if_then_else_parallelized( &self, condition: &BooleanBlock, true_ct: &SignedRadixCiphertext, false_value: Scalar, ) -> Self::Output

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl ServerKeyDefaultCMux<&BooleanBlock, &BooleanBlock> for ServerKey

Source§

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);
        }
    }
}
Source§

type Output = BooleanBlock

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl<T> ServerKeyDefaultCMux<&T, &T> for ServerKey

Source§

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);
Source§

type Output = T

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseRadixCiphertext<Ciphertext>> for ServerKey
where Scalar: DecomposableInto<u64>,

Source§

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);
Source§

type Output = BaseRadixCiphertext<Ciphertext>

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl<Scalar> ServerKeyDefaultCMux<Scalar, &BaseSignedRadixCiphertext<Ciphertext>> for ServerKey
where Scalar: DecomposableInto<u64>,

Source§

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);
Source§

type Output = BaseSignedRadixCiphertext<Ciphertext>

Source§

fn select_parallelized( &self, condition: &BooleanBlock, ct_when_true: TrueCt, ct_when_false: FalseCt, ) -> Self::Output

Source§

fn cmux_parallelized( &self, condition: &BooleanBlock, true_ct: TrueCt, false_ct: FalseCt, ) -> Self::Output

Source§

impl Unversionize for ServerKey

Source§

fn unversionize( versioned: Self::VersionedOwned, ) -> Result<Self, UnversionizeError>

Creates an object from a versioned enum, and eventually upgrades from previous variants.
Source§

impl UnversionizeVec for ServerKey

Source§

impl Version for ServerKey

Source§

type Ref<'vers> = ServerKeyVersion<'vers>

Source§

type Owned = ServerKeyVersionOwned

Source§

impl Versionize for ServerKey

Source§

type Versioned<'vers> = <ServerKeyVersions as VersionsDispatch<ServerKey>>::Ref<'vers>

The equivalent versioned type. It should have a variant for each version. It may own the underlying data or only hold a read-only reference to it.
Source§

fn versionize(&self) -> Self::Versioned<'_>

Wraps the object into a versioned enum with a variant for each version. This will use references on the underlying types if possible.
Source§

impl VersionizeOwned for ServerKey

Source§

type VersionedOwned = <ServerKeyVersions as VersionsDispatch<ServerKey>>::Owned

Source§

fn versionize_owned(self) -> Self::VersionedOwned

Wraps the object into a versioned enum with a variant for each version. This will clone the underlying types.
Source§

impl VersionizeSlice for ServerKey

Source§

type VersionedSlice<'vers> = Vec<<ServerKey as Versionize>::Versioned<'vers>>

Source§

fn versionize_slice(slice: &[Self]) -> Self::VersionedSlice<'_>

Source§

impl VersionizeVec for ServerKey

Source§

impl VersionsDispatch<ServerKey> for ServerKeyVersions

Source§

type Ref<'vers> = ServerKeyVersionsDispatch<'vers>

Source§

type Owned = ServerKeyVersionsDispatchOwned

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Input, Output> CastInto<Output> for Input
where Output: CastFrom<Input>,

Source§

fn cast_into(self) -> Output

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,