mirror of
https://github.com/arnaucube/fhe-study.git
synced 2026-01-24 04:33:52 +01:00
tfhe: add CMux gate
This commit is contained in:
@@ -35,9 +35,13 @@ impl<const K: usize> TGSW<K> {
|
|||||||
pub fn from_tlwe(_tlwe: TLWE<K>) -> Self {
|
pub fn from_tlwe(_tlwe: TLWE<K>) -> Self {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cmux(bit: Self, ct1: TLWE<K>, ct2: TLWE<K>) -> TLWE<K> {
|
||||||
|
ct1.clone() + (bit * (ct2 - ct1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// external product TGSW x TLWE
|
/// External product TGSW x TLWE
|
||||||
impl<const K: usize> Mul<TLWE<K>> for TGSW<K> {
|
impl<const K: usize> Mul<TLWE<K>> for TGSW<K> {
|
||||||
type Output = TLWE<K>;
|
type Output = TLWE<K>;
|
||||||
|
|
||||||
@@ -105,8 +109,7 @@ mod tests {
|
|||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let msg_dist = Uniform::new(0_u64, T);
|
let msg_dist = Uniform::new(0_u64, T);
|
||||||
|
|
||||||
for i in 0..50 {
|
for _ in 0..50 {
|
||||||
dbg!(&i);
|
|
||||||
let (sk, _) = TLWE::<K>::new_key(&mut rng)?;
|
let (sk, _) = TLWE::<K>::new_key(&mut rng)?;
|
||||||
|
|
||||||
let m1: Rq<T, 1> = Rq::rand_u64(&mut rng, msg_dist)?;
|
let m1: Rq<T, 1> = Rq::rand_u64(&mut rng, msg_dist)?;
|
||||||
@@ -131,4 +134,47 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cmux() -> Result<()> {
|
||||||
|
const T: u64 = 2; // plaintext modulus
|
||||||
|
const K: usize = 32;
|
||||||
|
|
||||||
|
let beta: u32 = 2;
|
||||||
|
let l: u32 = 64;
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let msg_dist = Uniform::new(0_u64, T);
|
||||||
|
|
||||||
|
for _ in 0..50 {
|
||||||
|
let (sk, _) = TLWE::<K>::new_key(&mut rng)?;
|
||||||
|
|
||||||
|
let m1: Rq<T, 1> = Rq::rand_u64(&mut rng, msg_dist)?;
|
||||||
|
let p1: T64 = TLWE::<K>::encode::<T>(&m1); // scaled by delta
|
||||||
|
|
||||||
|
let m2: Rq<T, 1> = Rq::rand_u64(&mut rng, msg_dist)?;
|
||||||
|
let p2: T64 = TLWE::<K>::encode::<T>(&m2); // scaled by delta
|
||||||
|
|
||||||
|
for bit_raw in 0..2 {
|
||||||
|
let bit = TGSW::<K>::encrypt_s(&mut rng, beta, l, &sk, &T64(bit_raw))?;
|
||||||
|
|
||||||
|
let c1 = TLWE::<K>::encrypt_s(&mut rng, &sk, &p1)?;
|
||||||
|
let c2 = TLWE::<K>::encrypt_s(&mut rng, &sk, &p2)?;
|
||||||
|
|
||||||
|
let res: TLWE<K> = TGSW::cmux(bit, c1, c2);
|
||||||
|
|
||||||
|
let p_recovered = res.decrypt(&sk);
|
||||||
|
// downscaled by delta^-1
|
||||||
|
let res_recovered = TLWE::<K>::decode::<T>(&p_recovered);
|
||||||
|
|
||||||
|
if bit_raw == 0 {
|
||||||
|
assert_eq!(m1, res_recovered);
|
||||||
|
} else {
|
||||||
|
assert_eq!(m2, res_recovered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user