Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the high-level API for Integer ciphertexts with template arguments #510

Closed
cgouert opened this issue Aug 28, 2023 · 2 comments
Closed

Comments

@cgouert
Copy link

cgouert commented Aug 28, 2023

We're trying to write a single function that utilizes the overloaded arithmetic functions for integer ciphertexts for any of the supported ciphertext sizes (FheUint32, FheUint64, etc.). However, we seem to have issues setting the proper traits; as an example, let's say we want to compute an add between an FheUint32 and a plaintext value represented by a u32 with the following code:

pub fn eval_ct_pt_add<P, C>(
    &mut self,
    ct: &C,
    pt: P,
) -> C {
    ct + pt
}

what would be appropriate trait constraints for C and P in this case? For instance, if we fix C to be FheUint32, we encounter the following error for P (when passing a u32):

the trait bound P: Borrow<tfhe::high_level_api::integers::types::base::GenericInteger<tfhe::high_level_api::integers::types::static_::FheUint32Parameters>> is not satisfied

cc: @jimouris

@tmontaigu
Copy link
Contributor

The trait bounds for operators +,-,*,>>,etc are the traits from std::ops, like std::ops::Add (for +)

So you have to write the correct where clause, it can get complex if you are not used to it and want to write the trait bounds for references to avoid using .clone() everywhere.

The old docs from concrete has an page on it that we haven't migrated to tfhe-rs https://docs.zama.ai/concrete/v/0.2-1/how-to/generic_bounds

use std::ops::{Add, Mul};

use tfhe::prelude::*;
use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint32, FheUint64};

pub fn ex1<'a, FheType, ClearType>(ct: &'a FheType, pt: ClearType) -> FheType
where
    &'a FheType: Add<ClearType, Output = FheType>,
{
   ct + pt
}

pub fn ex2<'a, FheType, ClearType>(a: &'a FheType, b: &'a FheType, pt: ClearType) -> FheType
where
    &'a FheType: Mul<&'a FheType, Output = FheType>,
    FheType: Add<ClearType, Output = FheType>,
{
    (a * b) + pt
}

pub fn ex3<FheType, ClearType>(a: FheType, b: FheType, pt: ClearType) -> FheType
where
    for<'a> &'a FheType: Add<&'a FheType, Output = FheType>,
    FheType: Add<FheType, Output = FheType> + Add<ClearType, Output = FheType>,
{
    let  tmp = (&a + &b) + (&a + &b);
    tmp + pt
}

pub fn ex4<FheType, ClearType>(a: FheType, b: FheType, pt: ClearType) -> FheType
where
    FheType: Clone + Add<FheType, Output = FheType> + Add<ClearType, Output = FheType>,
{
    let  tmp = (a.clone() + b.clone()) + (a.clone() + b.clone());
    tmp + pt
}


fn main() {
    let config = ConfigBuilder::all_disabled()
        .enable_default_integers()
        .build();

    let (client_key, server_keys) = generate_keys(config);
    
    set_server_key(server_keys);
  
    let a = FheUint32::try_encrypt(46546u32, &client_key).unwrap();
    let b = FheUint32::try_encrypt(6469u32, &client_key).unwrap();
    let c = 64u32;
    let result = ex1(&a, c);
    let result = ex2(&a, &b, c);
    let result = ex3(a.clone(), b.clone(), c);
    let result = ex4(a, b, c);
    
    let a = FheUint64::try_encrypt(46546u64, &client_key).unwrap();
    let b = FheUint64::try_encrypt(6469u64, &client_key).unwrap();
    let c = 64u64;
    let result = ex1(&a, c);
    let result = ex2(&a, &b, c);
    let result = ex3(a.clone(), b.clone(), c);
    let result = ex4(a, b, c);
}

@cgouert
Copy link
Author

cgouert commented Aug 29, 2023

great, thanks for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants