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}