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}