concrete_shortint/server_key/div_mod.rs
1use super::ServerKey;
2use crate::engine::ShortintEngine;
3use crate::Ciphertext;
4
5impl ServerKey {
6 /// Compute a division between two ciphertexts without checks.
7 ///
8 /// The result is returned in a _new_ ciphertext.
9 ///
10 /// # Warning
11 ///
12 /// /!\ A division by zero returns 0!
13 ///
14 /// # Example
15 ///
16 ///```rust
17 /// use concrete_shortint::gen_keys;
18 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
19 ///
20 /// // Generate the client key and the server key
21 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
22 ///
23 /// let clear_1 = 1;
24 /// let clear_2 = 2;
25 ///
26 /// // Encrypt two messages
27 /// let ct_1 = cks.encrypt(clear_1);
28 /// let ct_2 = cks.encrypt(clear_2);
29 ///
30 /// // Compute homomorphically a multiplication
31 /// let ct_res = sks.unchecked_div(&ct_1, &ct_2);
32 ///
33 /// // Decrypt
34 /// let res = cks.decrypt(&ct_res);
35 /// assert_eq!(clear_1 / clear_2, res);
36 /// ```
37 pub fn unchecked_div(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> Ciphertext {
38 ShortintEngine::with_thread_local_mut(|engine| {
39 engine.unchecked_div(self, ct_left, ct_right).unwrap()
40 })
41 }
42
43 /// Compute a division between two ciphertexts without checks.
44 ///
45 /// The result is _assigned_ in `ct_left`.
46 ///
47 /// # Warning
48 ///
49 /// /!\ A division by zero returns 0!
50 ///
51 /// # Example
52 ///
53 ///```rust
54 /// use concrete_shortint::gen_keys;
55 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
56 ///
57 /// // Generate the client key and the server key
58 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
59 ///
60 /// let clear_1 = 1;
61 /// let clear_2 = 2;
62 ///
63 /// // Encrypt two messages
64 /// let mut ct_1 = cks.encrypt(clear_1);
65 /// let ct_2 = cks.encrypt(clear_2);
66 ///
67 /// // Compute homomorphically a multiplication
68 /// sks.unchecked_div_assign(&mut ct_1, &ct_2);
69 ///
70 /// // Decrypt
71 /// let res = cks.decrypt(&ct_1);
72 /// assert_eq!(clear_1 / clear_2, res);
73 /// ```
74 pub fn unchecked_div_assign(&self, ct_left: &mut Ciphertext, ct_right: &Ciphertext) {
75 ShortintEngine::with_thread_local_mut(|engine| {
76 engine
77 .unchecked_div_assign(self, ct_left, ct_right)
78 .unwrap()
79 })
80 }
81
82 /// Compute a division between two ciphertexts.
83 ///
84 /// The result is returned in a _new_ ciphertext.
85 ///
86 /// # Warning
87 ///
88 /// /!\ A division by zero returns 0!
89 ///
90 /// # Example
91 ///
92 ///```rust
93 /// use concrete_shortint::gen_keys;
94 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
95 ///
96 /// // Generate the client key and the server key
97 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
98 ///
99 /// let clear_1 = 1;
100 /// let clear_2 = 2;
101 ///
102 /// // Encrypt two messages
103 /// let mut ct_1 = cks.encrypt(clear_1);
104 /// let mut ct_2 = cks.encrypt(clear_2);
105 ///
106 /// // Compute homomorphically a multiplication
107 /// let ct_res = sks.smart_div(&mut ct_1, &mut ct_2);
108 ///
109 /// // Decrypt
110 /// let res = cks.decrypt(&ct_res);
111 /// assert_eq!(clear_1 / clear_2, res);
112 /// ```
113 pub fn smart_div(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) -> Ciphertext {
114 ShortintEngine::with_thread_local_mut(|engine| {
115 engine.smart_div(self, ct_left, ct_right).unwrap()
116 })
117 }
118
119 /// Compute a division between two ciphertexts without checks.
120 ///
121 /// The result is _assigned_ in `ct_left`.
122 ///
123 /// # Warning
124 ///
125 /// /!\ A division by zero returns 0!
126 ///
127 /// # Example
128 ///
129 ///```rust
130 /// use concrete_shortint::gen_keys;
131 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
132 ///
133 /// // Generate the client key and the server key
134 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
135 ///
136 /// let clear_1 = 3;
137 /// let clear_2 = 2;
138 ///
139 /// // Encrypt two messages
140 /// let mut ct_1 = cks.encrypt(clear_1);
141 /// let mut ct_2 = cks.encrypt(clear_2);
142 ///
143 /// // Compute homomorphically a multiplication
144 /// sks.unchecked_div_assign(&mut ct_1, &ct_2);
145 ///
146 /// // Decrypt
147 /// let res = cks.decrypt(&ct_1);
148 /// assert_eq!(clear_1 / clear_2, res);
149 /// ```
150 pub fn smart_div_assign(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) {
151 ShortintEngine::with_thread_local_mut(|engine| {
152 engine.smart_div_assign(self, ct_left, ct_right).unwrap()
153 })
154 }
155
156 /// Compute a division of a ciphertext by a scalar without checks.
157 ///
158 /// # Panics
159 ///
160 /// This function will panic if `scalar == 0`.
161 ///
162 /// # Example
163 ///
164 ///```rust
165 /// use concrete_shortint::gen_keys;
166 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
167 ///
168 /// // Generate the client key and the server key
169 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
170 ///
171 /// let clear_1 = 3;
172 /// let clear_2 = 2;
173 ///
174 /// // Encrypt one message
175 /// let mut ct_1 = cks.encrypt(clear_1);
176 ///
177 /// // Compute homomorphically a multiplication
178 /// let ct_res = sks.unchecked_scalar_div(&mut ct_1, clear_2);
179 ///
180 /// // Decrypt
181 /// let res = cks.decrypt(&ct_res);
182 /// assert_eq!(clear_1 / (clear_2 as u64), res);
183 /// ```
184 pub fn unchecked_scalar_div(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
185 ShortintEngine::with_thread_local_mut(|engine| {
186 engine.unchecked_scalar_div(self, ct_left, scalar).unwrap()
187 })
188 }
189
190 pub fn unchecked_scalar_div_assign(&self, ct_left: &mut Ciphertext, scalar: u8) {
191 ShortintEngine::with_thread_local_mut(|engine| {
192 engine
193 .unchecked_scalar_div_assign(self, ct_left, scalar)
194 .unwrap()
195 })
196 }
197
198 /// Computes homomorphically a modular reduction without checks.
199 ///
200 /// # Panics
201 ///
202 /// This function will panic if `modulus == 0`.
203 ///
204 /// # Example
205 ///
206 /// ```rust
207 /// use concrete_shortint::gen_keys;
208 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
209 ///
210 /// // Generate the client key and the server key:
211 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
212 ///
213 /// let msg = 3;
214 ///
215 /// let mut ct = cks.encrypt(msg);
216 ///
217 /// let modulus: u8 = 2;
218 /// // Compute homomorphically an addition:
219 /// let ct_res = sks.unchecked_scalar_mod(&mut ct, modulus);
220 ///
221 /// // Decrypt:
222 /// let dec = cks.decrypt(&ct_res);
223 /// assert_eq!(1, dec);
224 /// ```
225 pub fn unchecked_scalar_mod(&self, ct_left: &Ciphertext, modulus: u8) -> Ciphertext {
226 ShortintEngine::with_thread_local_mut(|engine| {
227 engine.unchecked_scalar_mod(self, ct_left, modulus).unwrap()
228 })
229 }
230
231 pub fn unchecked_scalar_mod_assign(&self, ct_left: &mut Ciphertext, modulus: u8) {
232 ShortintEngine::with_thread_local_mut(|engine| {
233 engine
234 .unchecked_scalar_mod_assign(self, ct_left, modulus)
235 .unwrap()
236 })
237 }
238}