add div by zero
Janmajaya Mall janmajayamall@protonmail.com
Mon, 01 Jul 2024 11:48:10 +0530
4 files changed,
44 insertions(+),
12 deletions(-)
M
src/bool/mp_api.rs
→
src/bool/mp_api.rs
@@ -508,13 +508,15 @@ #[cfg(feature = "interactive_mp")]
fn all_uint8_apis() { use num_traits::Euclid; + use crate::div_zero_error_flag; + set_single_party_parameter_sets(SP_TEST_BOOL_PARAMS); let (ck, sk) = gen_keys(); sk.set_server_key(); - for i in 144..=255 { - for j in 100..=255 { + for i in 0..=255 { + for j in 0..=255 { let m0 = i; let m1 = j; let c0 = ck.encrypt(&m0);@@ -574,7 +576,7 @@ q
); assert_eq!( m_remainder, r, - "Expected {} but got {m_quotient} for {i}%{j}", + "Expected {} but got {m_remainder} for {i}%{j}", r ); } else {@@ -584,8 +586,14 @@ "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" - ) + "Expected {i} but got {m_remainder}. Case div by zero" + ); + + let div_by_zero = ck.decrypt(&div_zero_error_flag().unwrap()); + assert_eq!( + div_by_zero, true, + "Expected true but got {div_by_zero}" + ); } } }
M
src/lib.rs
→
src/lib.rs
@@ -22,7 +22,7 @@ // gen_mp_keys_phase1, gen_mp_keys_phase2, set_mp_seed, set_parameter_set,
// ParameterSelector, }; pub use bool::*; pub use ntt::{Ntt, NttBackendU64, NttInit}; -pub use shortint::FheUint8; +pub use shortint::{div_zero_error_flag, FheUint8}; pub use decomposer::{Decomposer, DecomposerIter, DefaultDecomposer};
M
src/shortint/mod.rs
→
src/shortint/mod.rs
@@ -5,8 +5,20 @@
pub type FheUint8 = enc_dec::FheUint8<Vec<u64>>; pub type FheBool = Vec<u64>; +use std::cell::RefCell; + use crate::bool::{evaluator::BooleanGates, BoolEvaluator, RuntimeServerKey}; +thread_local! { + static DIV_ZERO_ERROR: RefCell<Option<FheBool>> = RefCell::new(None); +} + +/// Returns Boolean ciphertext indicating whether last division was attempeted +/// with decnomiantor set to 0. +pub fn div_zero_error_flag() -> Option<Vec<u64>> { + DIV_ZERO_ERROR.with_borrow(|c| c.clone()) +} + mod frontend { use super::ops::{ arbitrary_bit_adder, arbitrary_bit_division_for_quotient_and_rem, arbitrary_bit_subtractor,@@ -17,6 +29,8 @@
use super::*; mod arithetic { + + use ops::is_zero; use super::*; use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};@@ -64,9 +78,13 @@
impl Div<&FheUint8> for &FheUint8 { type Output = FheUint8; fn div(self, rhs: &FheUint8) -> Self::Output { - // TODO(Jay:) Figure out how to set zero error flag BoolEvaluator::with_local_mut(|e| { let key = RuntimeServerKey::global(); + + // set div by 0 error flag + let is_zero = is_zero(e, rhs.data(), key); + DIV_ZERO_ERROR.set(Some(is_zero)); + let (quotient, _) = arbitrary_bit_division_for_quotient_and_rem( e, self.data(),@@ -125,9 +143,13 @@ })
} 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 = RuntimeServerKey::global(); + + // set div by 0 error flag + let is_zero = is_zero(e, rhs.data(), key); + DIV_ZERO_ERROR.set(Some(is_zero)); + let (quotient, remainder) = arbitrary_bit_division_for_quotient_and_rem( e, self.data(),@@ -141,9 +163,7 @@ }
} mod booleans { - use crate::shortint::ops::{ - arbitrary_bit_comparator, arbitrary_bit_equality, arbitrary_signed_bit_comparator, - }; + use crate::shortint::ops::{arbitrary_bit_comparator, arbitrary_bit_equality}; use super::*;
M
src/shortint/ops.rs
→
src/shortint/ops.rs
@@ -256,7 +256,11 @@
(quotient, remainder) } -fn is_zero<E: BooleanGates>(evaluator: &mut E, a: &[E::Ciphertext], key: &E::Key) -> E::Ciphertext { +pub(super) fn is_zero<E: BooleanGates>( + evaluator: &mut E, + a: &[E::Ciphertext], + key: &E::Key, +) -> E::Ciphertext { let mut a = a.iter().map(|v| evaluator.not(v)).collect_vec(); let (out, rest_a) = a.split_at_mut(1); rest_a.iter().for_each(|c| {