|
@ -5,49 +5,12 @@ use crate::{ |
|
|
utils::{Global, WithLocal},
|
|
|
utils::{Global, WithLocal},
|
|
|
Decryptor, Encryptor,
|
|
|
Decryptor, Encryptor,
|
|
|
};
|
|
|
};
|
|
|
use ops::{
|
|
|
|
|
|
arbitrary_bit_adder, arbitrary_bit_division_for_quotient_and_rem, arbitrary_bit_subtractor,
|
|
|
|
|
|
eight_bit_mul,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
mod ops;
|
|
|
mod ops;
|
|
|
mod types;
|
|
|
mod types;
|
|
|
|
|
|
|
|
|
type FheUint8 = types::FheUint8<Vec<u64>>;
|
|
|
type FheUint8 = types::FheUint8<Vec<u64>>;
|
|
|
|
|
|
|
|
|
fn add_mut(a: &mut FheUint8, b: &FheUint8) {
|
|
|
|
|
|
BoolEvaluator::with_local_mut_mut(&mut |e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
arbitrary_bit_adder(e, a.data_mut(), b.data(), false, key);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn sub(a: &FheUint8, b: &FheUint8) -> FheUint8 {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (out, _, _) = arbitrary_bit_subtractor(e, a.data(), b.data(), key);
|
|
|
|
|
|
FheUint8 { data: out }
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn mul(a: &FheUint8, b: &FheUint8) -> FheUint8 {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let out = eight_bit_mul(e, a.data(), b.data(), key);
|
|
|
|
|
|
FheUint8 { data: out }
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn div(a: &FheUint8, b: &FheUint8) -> (FheUint8, FheUint8) {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (quotient, remainder) =
|
|
|
|
|
|
arbitrary_bit_division_for_quotient_and_rem(e, a.data(), b.data(), key);
|
|
|
|
|
|
|
|
|
|
|
|
(FheUint8 { data: quotient }, FheUint8 { data: remainder })
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Encryptor<u8, FheUint8> for ClientKey {
|
|
|
impl Encryptor<u8, FheUint8> for ClientKey {
|
|
|
fn encrypt(&self, m: &u8) -> FheUint8 {
|
|
|
fn encrypt(&self, m: &u8) -> FheUint8 {
|
|
|
let cts = (0..8)
|
|
|
let cts = (0..8)
|
|
@ -84,9 +47,11 @@ mod frontend { |
|
|
utils::{Global, WithLocal},
|
|
|
utils::{Global, WithLocal},
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
use super::{add_mut, div, mul, FheUint8};
|
|
|
|
|
|
|
|
|
use super::FheUint8;
|
|
|
|
|
|
|
|
|
mod arithetic {
|
|
|
mod arithetic {
|
|
|
|
|
|
use crate::bool::{evaluator::BooleanGates, FheBool};
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
use super::*;
|
|
|
use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};
|
|
|
use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};
|
|
|
|
|
|
|
|
@ -113,7 +78,7 @@ mod frontend { |
|
|
fn sub(self, rhs: &FheUint8) -> Self::Output {
|
|
|
fn sub(self, rhs: &FheUint8) -> Self::Output {
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
let (out, _, _) = arbitrary_bit_subtractor(e, self.data(), self.data(), key);
|
|
|
|
|
|
|
|
|
let (out, _, _) = arbitrary_bit_subtractor(e, self.data(), rhs.data(), key);
|
|
|
FheUint8 { data: out }
|
|
|
FheUint8 { data: out }
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
@ -133,6 +98,7 @@ mod frontend { |
|
|
impl Div<&FheUint8> for &FheUint8 {
|
|
|
impl Div<&FheUint8> for &FheUint8 {
|
|
|
type Output = FheUint8;
|
|
|
type Output = FheUint8;
|
|
|
fn div(self, rhs: &FheUint8) -> Self::Output {
|
|
|
fn div(self, rhs: &FheUint8) -> Self::Output {
|
|
|
|
|
|
// TODO(Jay:) Figure out how to set zero error flag
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
let (quotient, _) = arbitrary_bit_division_for_quotient_and_rem(
|
|
|
let (quotient, _) = arbitrary_bit_division_for_quotient_and_rem(
|
|
@ -161,9 +127,120 @@ mod frontend { |
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl FheUint8 {
|
|
|
|
|
|
pub fn overflowing_add_assign(&mut self, rhs: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut_mut(&mut |e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (overflow, _) =
|
|
|
|
|
|
arbitrary_bit_adder(e, self.data_mut(), rhs.data(), false, key);
|
|
|
|
|
|
overflow
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn overflowing_add(self, rhs: &FheUint8) -> (FheUint8, FheBool) {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let mut lhs = self.clone();
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (overflow, _) =
|
|
|
|
|
|
arbitrary_bit_adder(e, lhs.data_mut(), rhs.data(), false, key);
|
|
|
|
|
|
(lhs, overflow)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn overflowing_sub(&self, rhs: &FheUint8) -> (FheUint8, FheBool) {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (out, mut overflow, _) =
|
|
|
|
|
|
arbitrary_bit_subtractor(e, self.data(), rhs.data(), key);
|
|
|
|
|
|
e.not_inplace(&mut overflow);
|
|
|
|
|
|
(FheUint8 { data: out }, overflow)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn div_rem(&self, rhs: &FheUint8) -> (FheUint8, FheUint8) {
|
|
|
|
|
|
// TODO(Jay:) Figure out how to set zero error flag
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let (quotient, remainder) = arbitrary_bit_division_for_quotient_and_rem(
|
|
|
|
|
|
e,
|
|
|
|
|
|
self.data(),
|
|
|
|
|
|
rhs.data(),
|
|
|
|
|
|
key,
|
|
|
|
|
|
);
|
|
|
|
|
|
(FheUint8 { data: quotient }, FheUint8 { data: remainder })
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
mod booleans {}
|
|
|
|
|
|
|
|
|
mod booleans {
|
|
|
|
|
|
use crate::{
|
|
|
|
|
|
bool::{evaluator::BooleanGates, FheBool},
|
|
|
|
|
|
shortint::ops::{
|
|
|
|
|
|
arbitrary_bit_comparator, arbitrary_bit_equality, arbitrary_signed_bit_comparator,
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
impl FheUint8 {
|
|
|
|
|
|
/// a == b
|
|
|
|
|
|
pub fn eq(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
arbitrary_bit_equality(e, self.data(), other.data(), key)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// a != b
|
|
|
|
|
|
pub fn neq(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let mut is_equal = arbitrary_bit_equality(e, self.data(), other.data(), key);
|
|
|
|
|
|
e.not_inplace(&mut is_equal);
|
|
|
|
|
|
is_equal
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// a < b
|
|
|
|
|
|
pub fn lt(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
arbitrary_bit_comparator(e, other.data(), self.data(), key)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// a > b
|
|
|
|
|
|
pub fn gt(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
arbitrary_bit_comparator(e, self.data(), other.data(), key)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// a <= b
|
|
|
|
|
|
pub fn le(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let mut a_greater_b =
|
|
|
|
|
|
arbitrary_bit_comparator(e, self.data(), other.data(), key);
|
|
|
|
|
|
e.not_inplace(&mut a_greater_b);
|
|
|
|
|
|
a_greater_b
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// a >= b
|
|
|
|
|
|
pub fn ge(&self, other: &FheUint8) -> FheBool {
|
|
|
|
|
|
BoolEvaluator::with_local_mut(|e| {
|
|
|
|
|
|
let key = ServerKeyEvaluationDomain::global();
|
|
|
|
|
|
let mut a_less_b = arbitrary_bit_comparator(e, other.data(), self.data(), key);
|
|
|
|
|
|
e.not_inplace(&mut a_less_b);
|
|
|
|
|
|
a_less_b
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
#[cfg(test)]
|
|
@ -175,19 +252,19 @@ mod tests { |
|
|
evaluator::{gen_keys, set_parameter_set, BoolEvaluator},
|
|
|
evaluator::{gen_keys, set_parameter_set, BoolEvaluator},
|
|
|
parameters::SP_BOOL_PARAMS,
|
|
|
parameters::SP_BOOL_PARAMS,
|
|
|
},
|
|
|
},
|
|
|
shortint::{add_mut, div, mul, sub, types::FheUint8},
|
|
|
|
|
|
|
|
|
shortint::types::FheUint8,
|
|
|
Decryptor, Encryptor,
|
|
|
Decryptor, Encryptor,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
#[test]
|
|
|
fn qwerty() {
|
|
|
|
|
|
|
|
|
fn all_uint8_apis() {
|
|
|
set_parameter_set(&SP_BOOL_PARAMS);
|
|
|
set_parameter_set(&SP_BOOL_PARAMS);
|
|
|
|
|
|
|
|
|
let (ck, sk) = gen_keys();
|
|
|
let (ck, sk) = gen_keys();
|
|
|
sk.set_server_key();
|
|
|
sk.set_server_key();
|
|
|
|
|
|
|
|
|
for i in 1..=255 {
|
|
|
|
|
|
for j in 0..=255 {
|
|
|
|
|
|
|
|
|
for i in 144..=255 {
|
|
|
|
|
|
for j in 100..=255 {
|
|
|
let m0 = i;
|
|
|
let m0 = i;
|
|
|
let m1 = j;
|
|
|
let m1 = j;
|
|
|
let c0 = ck.encrypt(&m0);
|
|
|
let c0 = ck.encrypt(&m0);
|
|
@ -196,66 +273,133 @@ mod tests { |
|
|
assert!(ck.decrypt(&c0) == m0);
|
|
|
assert!(ck.decrypt(&c0) == m0);
|
|
|
assert!(ck.decrypt(&c1) == m1);
|
|
|
assert!(ck.decrypt(&c1) == m1);
|
|
|
|
|
|
|
|
|
// Add
|
|
|
|
|
|
// let mut c_m0_plus_m1 = FheUint8 {
|
|
|
|
|
|
// data: c0.data().to_vec(),
|
|
|
|
|
|
// };
|
|
|
|
|
|
// add_mut(&mut c_m0_plus_m1, &c1);
|
|
|
|
|
|
// let m0_plus_m1 = ck.decrypt(&c_m0_plus_m1);
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m0_plus_m1,
|
|
|
|
|
|
// m0.wrapping_add(m1),
|
|
|
|
|
|
// "Expected {} but got {m0_plus_m1} for {i}+{j}",
|
|
|
|
|
|
// m0.wrapping_add(m1)
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
// Sub
|
|
|
|
|
|
// let c_sub = sub(&c0, &c1);
|
|
|
|
|
|
// let m0_sub_m1 = ck.decrypt(&c_sub);
|
|
|
|
|
|
// dbg!(m0, m1, m0_sub_m1);
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m0_sub_m1,
|
|
|
|
|
|
// m0.wrapping_sub(m1),
|
|
|
|
|
|
// "Expected {} but got {m0_sub_m1} for {i}-{j}",
|
|
|
|
|
|
// m0.wrapping_sub(m1)
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
// Mul
|
|
|
|
|
|
// let c_m0m1 = mul(&c0, &c1);
|
|
|
|
|
|
// let m0m1 = ck.decrypt(&c_m0m1);
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m0m1,
|
|
|
|
|
|
// m0.wrapping_mul(m1),
|
|
|
|
|
|
// "Expected {} but got {m0m1} for {i}x{j}",
|
|
|
|
|
|
// m0.wrapping_mul(m1)
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
// Div
|
|
|
|
|
|
// let (c_quotient, c_rem) = div(&c0, &c1);
|
|
|
|
|
|
// let m_quotient = ck.decrypt(&c_quotient);
|
|
|
|
|
|
// let m_remainder = ck.decrypt(&c_rem);
|
|
|
|
|
|
// if j != 0 {
|
|
|
|
|
|
// let (q, r) = i.div_rem_euclid(&j);
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m_quotient, q,
|
|
|
|
|
|
// "Expected {} but got {m_quotient} for {i}/{j}",
|
|
|
|
|
|
// q
|
|
|
|
|
|
// );
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m_remainder, r,
|
|
|
|
|
|
// "Expected {} but got {m_quotient} for {i}%{j}",
|
|
|
|
|
|
// r
|
|
|
|
|
|
// );
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m_quotient, 255,
|
|
|
|
|
|
// "Expected 255 but got {m_quotient}. Case div by zero"
|
|
|
|
|
|
// );
|
|
|
|
|
|
// assert_eq!(
|
|
|
|
|
|
// m_remainder, i,
|
|
|
|
|
|
// "Expected {i} but got {m_quotient}. Case div by zero"
|
|
|
|
|
|
// )
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
// Arithmetic
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
|
|
|
|
|
// Add
|
|
|
|
|
|
let mut c_m0_plus_m1 = FheUint8 {
|
|
|
|
|
|
data: c0.data().to_vec(),
|
|
|
|
|
|
};
|
|
|
|
|
|
c_m0_plus_m1 += &c1;
|
|
|
|
|
|
let m0_plus_m1 = ck.decrypt(&c_m0_plus_m1);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m0_plus_m1,
|
|
|
|
|
|
m0.wrapping_add(m1),
|
|
|
|
|
|
"Expected {} but got {m0_plus_m1} for {i}+{j}",
|
|
|
|
|
|
m0.wrapping_add(m1)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// Sub
|
|
|
|
|
|
let c_sub = &c0 - &c1;
|
|
|
|
|
|
let m0_sub_m1 = ck.decrypt(&c_sub);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m0_sub_m1,
|
|
|
|
|
|
m0.wrapping_sub(m1),
|
|
|
|
|
|
"Expected {} but got {m0_sub_m1} for {i}-{j}",
|
|
|
|
|
|
m0.wrapping_sub(m1)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
// Mul
|
|
|
|
|
|
let c_m0m1 = &c0 * &c1;
|
|
|
|
|
|
let m0m1 = ck.decrypt(&c_m0m1);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m0m1,
|
|
|
|
|
|
m0.wrapping_mul(m1),
|
|
|
|
|
|
"Expected {} but got {m0m1} for {i}x{j}",
|
|
|
|
|
|
m0.wrapping_mul(m1)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Div & Rem
|
|
|
|
|
|
{
|
|
|
|
|
|
let (c_quotient, c_rem) = c0.div_rem(&c1);
|
|
|
|
|
|
let m_quotient = ck.decrypt(&c_quotient);
|
|
|
|
|
|
let m_remainder = ck.decrypt(&c_rem);
|
|
|
|
|
|
if j != 0 {
|
|
|
|
|
|
let (q, r) = i.div_rem_euclid(&j);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m_quotient, q,
|
|
|
|
|
|
"Expected {} but got {m_quotient} for {i}/{j}",
|
|
|
|
|
|
q
|
|
|
|
|
|
);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m_remainder, r,
|
|
|
|
|
|
"Expected {} but got {m_quotient} for {i}%{j}",
|
|
|
|
|
|
r
|
|
|
|
|
|
);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m_quotient, 255,
|
|
|
|
|
|
"Expected 255 but got {m_quotient}. Case div by zero"
|
|
|
|
|
|
);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
m_remainder, i,
|
|
|
|
|
|
"Expected {i} but got {m_quotient}. Case div by zero"
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Comparisons
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
|
|
|
|
|
let c_eq = c0.eq(&c1);
|
|
|
|
|
|
let is_eq = ck.decrypt(&c_eq);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
is_eq,
|
|
|
|
|
|
i == j,
|
|
|
|
|
|
"Expected {} but got {is_eq} for {i}=={j}",
|
|
|
|
|
|
i == j
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
let c_gt = c0.gt(&c1);
|
|
|
|
|
|
let is_gt = ck.decrypt(&c_gt);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
is_gt,
|
|
|
|
|
|
i > j,
|
|
|
|
|
|
"Expected {} but got {is_gt} for {i}>{j}",
|
|
|
|
|
|
i > j
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
let c_lt = c0.lt(&c1);
|
|
|
|
|
|
let is_lt = ck.decrypt(&c_lt);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
is_lt,
|
|
|
|
|
|
i < j,
|
|
|
|
|
|
"Expected {} but got {is_lt} for {i}<{j}",
|
|
|
|
|
|
i < j
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
let c_ge = c0.ge(&c1);
|
|
|
|
|
|
let is_ge = ck.decrypt(&c_ge);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
is_ge,
|
|
|
|
|
|
i >= j,
|
|
|
|
|
|
"Expected {} but got {is_ge} for {i}>={j}",
|
|
|
|
|
|
i >= j
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
let c_le = c0.le(&c1);
|
|
|
|
|
|
let is_le = ck.decrypt(&c_le);
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
is_le,
|
|
|
|
|
|
i <= j,
|
|
|
|
|
|
"Expected {} but got {is_le} for {i}<={j}",
|
|
|
|
|
|
i <= j
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|