arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
phantom-zone/src/shortint/mod.rs
src/shortint/mod.rsRaw
  1mod enc_dec;
  2mod ops;
  3
  4pub type FheUint8 = enc_dec::FheUint8<Vec<u64>>;
  5
  6use std::cell::RefCell;
  7
  8use crate::bool::{BoolEvaluator, BooleanGates, FheBool, RuntimeServerKey};
  9
 10thread_local! {
 11     static DIV_ZERO_ERROR: RefCell<Option<FheBool>> = RefCell::new(None);
 12}
 13
 14/// Returns Boolean ciphertext indicating whether last division was attempeted
 15/// with decnomiantor set to 0.
 16pub fn div_zero_error_flag() -> Option<FheBool> {
 17    DIV_ZERO_ERROR.with_borrow(|c| c.clone())
 18}
 19
 20mod frontend {
 21    use super::ops::{
 22        arbitrary_bit_adder, arbitrary_bit_division_for_quotient_and_rem, arbitrary_bit_subtractor,
 23        eight_bit_mul, is_zero,
 24    };
 25    use crate::utils::{Global, WithLocal};
 26
 27    use super::*;
 28
 29    /// Set Div by Zero flag after each divison. Div by zero flag is set to true
 30    /// if either 1 of the division executed in circuit evaluation has
 31    /// denominator set to 0.
 32    fn set_div_by_zero_flag(denominator: &FheUint8) {
 33        {
 34            BoolEvaluator::with_local_mut(|e| {
 35                let key = RuntimeServerKey::global();
 36                let is_zero = is_zero(e, denominator.data(), key);
 37                DIV_ZERO_ERROR.with_borrow_mut(|before_is_zero| {
 38                    if before_is_zero.is_none() {
 39                        *before_is_zero = Some(FheBool { data: is_zero });
 40                    } else {
 41                        e.or_inplace(before_is_zero.as_mut().unwrap().data_mut(), &is_zero, key);
 42                    }
 43                });
 44            })
 45        }
 46    }
 47
 48    mod arithetic {
 49
 50        use super::*;
 51        use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};
 52
 53        impl AddAssign<&FheUint8> for FheUint8 {
 54            fn add_assign(&mut self, rhs: &FheUint8) {
 55                BoolEvaluator::with_local_mut_mut(&mut |e| {
 56                    let key = RuntimeServerKey::global();
 57                    arbitrary_bit_adder(e, self.data_mut(), rhs.data(), false, key);
 58                });
 59            }
 60        }
 61
 62        impl Add<&FheUint8> for &FheUint8 {
 63            type Output = FheUint8;
 64            fn add(self, rhs: &FheUint8) -> Self::Output {
 65                let mut a = self.clone();
 66                a += rhs;
 67                a
 68            }
 69        }
 70
 71        impl Sub<&FheUint8> for &FheUint8 {
 72            type Output = FheUint8;
 73            fn sub(self, rhs: &FheUint8) -> Self::Output {
 74                BoolEvaluator::with_local_mut(|e| {
 75                    let key = RuntimeServerKey::global();
 76                    let (out, _, _) = arbitrary_bit_subtractor(e, self.data(), rhs.data(), key);
 77                    FheUint8 { data: out }
 78                })
 79            }
 80        }
 81
 82        impl Mul<&FheUint8> for &FheUint8 {
 83            type Output = FheUint8;
 84            fn mul(self, rhs: &FheUint8) -> Self::Output {
 85                BoolEvaluator::with_local_mut(|e| {
 86                    let key = RuntimeServerKey::global();
 87                    let out = eight_bit_mul(e, self.data(), rhs.data(), key);
 88                    FheUint8 { data: out }
 89                })
 90            }
 91        }
 92
 93        impl Div<&FheUint8> for &FheUint8 {
 94            type Output = FheUint8;
 95            fn div(self, rhs: &FheUint8) -> Self::Output {
 96                // set div by 0 error flag
 97                set_div_by_zero_flag(rhs);
 98
 99                BoolEvaluator::with_local_mut(|e| {
100                    let key = RuntimeServerKey::global();
101
102                    let (quotient, _) = arbitrary_bit_division_for_quotient_and_rem(
103                        e,
104                        self.data(),
105                        rhs.data(),
106                        key,
107                    );
108                    FheUint8 { data: quotient }
109                })
110            }
111        }
112
113        impl Rem<&FheUint8> for &FheUint8 {
114            type Output = FheUint8;
115            fn rem(self, rhs: &FheUint8) -> Self::Output {
116                BoolEvaluator::with_local_mut(|e| {
117                    let key = RuntimeServerKey::global();
118                    let (_, remainder) = arbitrary_bit_division_for_quotient_and_rem(
119                        e,
120                        self.data(),
121                        rhs.data(),
122                        key,
123                    );
124                    FheUint8 { data: remainder }
125                })
126            }
127        }
128
129        impl FheUint8 {
130            pub fn overflowing_add_assign(&mut self, rhs: &FheUint8) -> FheBool {
131                BoolEvaluator::with_local_mut_mut(&mut |e| {
132                    let key = RuntimeServerKey::global();
133                    let (overflow, _) =
134                        arbitrary_bit_adder(e, self.data_mut(), rhs.data(), false, key);
135                    FheBool { data: overflow }
136                })
137            }
138
139            pub fn overflowing_add(self, rhs: &FheUint8) -> (FheUint8, FheBool) {
140                BoolEvaluator::with_local_mut(|e| {
141                    let mut lhs = self.clone();
142                    let key = RuntimeServerKey::global();
143                    let (overflow, _) =
144                        arbitrary_bit_adder(e, lhs.data_mut(), rhs.data(), false, key);
145                    (lhs, FheBool { data: overflow })
146                })
147            }
148
149            pub fn overflowing_sub(&self, rhs: &FheUint8) -> (FheUint8, FheBool) {
150                BoolEvaluator::with_local_mut(|e| {
151                    let key = RuntimeServerKey::global();
152                    let (out, mut overflow, _) =
153                        arbitrary_bit_subtractor(e, self.data(), rhs.data(), key);
154                    e.not_inplace(&mut overflow);
155                    (FheUint8 { data: out }, FheBool { data: overflow })
156                })
157            }
158
159            pub fn div_rem(&self, rhs: &FheUint8) -> (FheUint8, FheUint8) {
160                // set div by 0 error flag
161                set_div_by_zero_flag(rhs);
162
163                BoolEvaluator::with_local_mut(|e| {
164                    let key = RuntimeServerKey::global();
165
166                    let (quotient, remainder) = arbitrary_bit_division_for_quotient_and_rem(
167                        e,
168                        self.data(),
169                        rhs.data(),
170                        key,
171                    );
172                    (FheUint8 { data: quotient }, FheUint8 { data: remainder })
173                })
174            }
175        }
176    }
177
178    mod booleans {
179        use crate::shortint::ops::{arbitrary_bit_comparator, arbitrary_bit_equality};
180
181        use super::*;
182
183        impl FheUint8 {
184            /// a == b
185            pub fn eq(&self, other: &FheUint8) -> FheBool {
186                BoolEvaluator::with_local_mut(|e| {
187                    let key = RuntimeServerKey::global();
188                    let out = arbitrary_bit_equality(e, self.data(), other.data(), key);
189                    FheBool { data: out }
190                })
191            }
192
193            /// a != b
194            pub fn neq(&self, other: &FheUint8) -> FheBool {
195                BoolEvaluator::with_local_mut(|e| {
196                    let key = RuntimeServerKey::global();
197                    let mut is_equal = arbitrary_bit_equality(e, self.data(), other.data(), key);
198                    e.not_inplace(&mut is_equal);
199                    FheBool { data: is_equal }
200                })
201            }
202
203            /// a < b
204            pub fn lt(&self, other: &FheUint8) -> FheBool {
205                BoolEvaluator::with_local_mut(|e| {
206                    let key = RuntimeServerKey::global();
207                    let out = arbitrary_bit_comparator(e, other.data(), self.data(), key);
208                    FheBool { data: out }
209                })
210            }
211
212            /// a > b
213            pub fn gt(&self, other: &FheUint8) -> FheBool {
214                BoolEvaluator::with_local_mut(|e| {
215                    let key = RuntimeServerKey::global();
216                    let out = arbitrary_bit_comparator(e, self.data(), other.data(), key);
217                    FheBool { data: out }
218                })
219            }
220
221            /// a <= b
222            pub fn le(&self, other: &FheUint8) -> FheBool {
223                BoolEvaluator::with_local_mut(|e| {
224                    let key = RuntimeServerKey::global();
225                    let mut a_greater_b =
226                        arbitrary_bit_comparator(e, self.data(), other.data(), key);
227                    e.not_inplace(&mut a_greater_b);
228                    FheBool { data: a_greater_b }
229                })
230            }
231
232            /// a >= b
233            pub fn ge(&self, other: &FheUint8) -> FheBool {
234                BoolEvaluator::with_local_mut(|e| {
235                    let key = RuntimeServerKey::global();
236                    let mut a_less_b = arbitrary_bit_comparator(e, other.data(), self.data(), key);
237                    e.not_inplace(&mut a_less_b);
238                    FheBool { data: a_less_b }
239                })
240            }
241        }
242    }
243}