concrete_shortint/server_key/comp_op.rs
1use super::ServerKey;
2use crate::engine::ShortintEngine;
3use crate::server_key::CheckError;
4use crate::server_key::CheckError::CarryFull;
5use crate::Ciphertext;
6
7// # Note:
8// _assign comparison operation are not made public (if they exists) as we don't think there are
9// uses for them. For instance: adding has an assign variants because you can do "+" and "+="
10// however, comparisons like equality do not have that, "==" does not have and "===",
11// ">=" is greater of equal, not greater_assign.
12
13impl ServerKey {
14 /// Implements the "greater" (`>`) operator between two ciphertexts without checks.
15 ///
16 /// # Example
17 ///
18 ///```rust
19 /// use concrete_shortint::gen_keys;
20 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
21 ///
22 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
23 ///
24 /// let msg_1 = 1;
25 /// let msg_2 = 2;
26 ///
27 /// // Encrypt two messages
28 /// let ct_left = cks.encrypt(msg_1);
29 /// let ct_right = cks.encrypt(msg_2);
30 ///
31 /// let ct_res = sks.unchecked_greater(&ct_left, &ct_right);
32 ///
33 /// // Decrypt
34 /// let res = cks.decrypt(&ct_res);
35 /// assert_eq!((msg_1 > msg_2) as u64, res);
36 /// ```
37 pub fn unchecked_greater(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> Ciphertext {
38 ShortintEngine::with_thread_local_mut(|engine| {
39 engine.unchecked_greater(self, ct_left, ct_right).unwrap()
40 })
41 }
42
43 /// Implements the "greater" (`>`) operator between two ciphertexts with checks.
44 ///
45 /// If the operation can be performed, the result is returned in a _new_ ciphertext.
46 /// Otherwise [CheckError::CarryFull] is returned.
47 ///
48 /// # Example
49 ///
50 /// ```rust
51 /// use concrete_shortint::gen_keys;
52 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
53 ///
54 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
55 ///
56 /// let msg_1 = 1;
57 /// let msg_2 = 2;
58 ///
59 /// // Encrypt two messages:
60 /// let ct_left = cks.encrypt(msg_1);
61 /// let ct_right = cks.encrypt(msg_2);
62 ///
63 /// let res = sks.checked_greater(&ct_left, &ct_right);
64 ///
65 /// assert!(res.is_ok());
66 /// let res = res.unwrap();
67 ///
68 /// let clear_res = cks.decrypt(&res);
69 /// assert_eq!((msg_1 > msg_2) as u64, clear_res);
70 /// ```
71 pub fn checked_greater(
72 &self,
73 ct_left: &Ciphertext,
74 ct_right: &Ciphertext,
75 ) -> Result<Ciphertext, CheckError> {
76 if self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
77 Ok(self.unchecked_greater(ct_left, ct_right))
78 } else {
79 Err(CarryFull)
80 }
81 }
82
83 /// Computes homomorphically a `>` between two ciphertexts encrypting integer values.
84 ///
85 /// This checks that the addition is possible. In the case where the carry buffers are full,
86 /// then it is automatically cleared to allow the operation.
87 /// # Example
88 ///
89 /// ```rust
90 /// use concrete_shortint::gen_keys;
91 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
92 ///
93 /// // Generate the client key and the server key:
94 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
95 ///
96 /// let msg = 1;
97 ///
98 /// // Encrypt two messages:
99 /// let mut ct1 = cks.encrypt(msg);
100 /// let mut ct2 = cks.encrypt(msg);
101 ///
102 /// // Compute homomorphically an OR:
103 /// let ct_res = sks.smart_greater(&mut ct1, &mut ct2);
104 ///
105 /// // Decrypt:
106 /// let res = cks.decrypt(&ct_res);
107 /// assert_eq!((msg > msg) as u64, res);
108 /// ```
109 pub fn smart_greater(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) -> Ciphertext {
110 ShortintEngine::with_thread_local_mut(|engine| {
111 engine.smart_greater(self, ct_left, ct_right).unwrap()
112 })
113 }
114
115 /// Implements the "greater or equal" (`>=`) operator between two ciphertexts without checks.
116 ///
117 /// # Example
118 ///
119 ///```rust
120 /// use concrete_shortint::gen_keys;
121 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
122 ///
123 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
124 ///
125 /// let msg_1 = 1;
126 /// let msg_2 = 2;
127 ///
128 /// // Encrypt two messages
129 /// let ct_left = cks.encrypt(msg_1);
130 /// let ct_right = cks.encrypt(msg_2);
131 ///
132 /// let ct_res = sks.unchecked_greater_or_equal(&ct_left, &ct_right);
133 ///
134 /// // Decrypt
135 /// let res = cks.decrypt(&ct_res);
136 /// assert_eq!((msg_1 >= msg_2) as u64, res);
137 /// ```
138 pub fn unchecked_greater_or_equal(
139 &self,
140 ct_left: &Ciphertext,
141 ct_right: &Ciphertext,
142 ) -> Ciphertext {
143 ShortintEngine::with_thread_local_mut(|engine| {
144 engine
145 .unchecked_greater_or_equal(self, ct_left, ct_right)
146 .unwrap()
147 })
148 }
149
150 /// Computes homomorphically a `>=` between two ciphertexts encrypting integer values.
151 ///
152 /// This checks that the addition is possible. In the case where the carry buffers are full,
153 /// then it is automatically cleared to allow the operation.
154 /// # Example
155 ///
156 /// ```rust
157 /// use concrete_shortint::gen_keys;
158 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
159 ///
160 /// // Generate the client key and the server key:
161 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
162 ///
163 /// let msg = 1;
164 ///
165 /// // Encrypt two messages:
166 /// let mut ct1 = cks.encrypt(msg);
167 /// let mut ct2 = cks.encrypt(msg);
168 ///
169 /// // Compute homomorphically an OR:
170 /// let ct_res = sks.smart_greater_or_equal(&mut ct1, &mut ct2);
171 ///
172 /// // Decrypt:
173 /// let res = cks.decrypt(&ct_res);
174 /// assert_eq!((msg >= msg) as u64, res);
175 /// ```
176 pub fn smart_greater_or_equal(
177 &self,
178 ct_left: &mut Ciphertext,
179 ct_right: &mut Ciphertext,
180 ) -> Ciphertext {
181 ShortintEngine::with_thread_local_mut(|engine| {
182 engine
183 .smart_greater_or_equal(self, ct_left, ct_right)
184 .unwrap()
185 })
186 }
187
188 /// Implements the "greater or equal" (`>=`) operator between two ciphertexts with checks.
189 ///
190 /// If the operation can be performed, the result is returned in a _new_ ciphertext.
191 /// Otherwise [CheckError::CarryFull] is returned.
192 ///
193 /// # Example
194 ///
195 /// ```rust
196 /// use concrete_shortint::gen_keys;
197 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
198 ///
199 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
200 ///
201 /// let msg_1 = 1;
202 /// let msg_2 = 2;
203 ///
204 /// // Encrypt two messages:
205 /// let ct_left = cks.encrypt(msg_1);
206 /// let ct_right = cks.encrypt(msg_2);
207 ///
208 /// let res = sks.checked_greater(&ct_left, &ct_right);
209 ///
210 /// assert!(res.is_ok());
211 /// let res = res.unwrap();
212 ///
213 /// let clear_res = cks.decrypt(&res);
214 /// assert_eq!((msg_1 >= msg_2) as u64, clear_res);
215 /// ```
216 pub fn checked_greater_or_equal(
217 &self,
218 ct_left: &Ciphertext,
219 ct_right: &Ciphertext,
220 ) -> Result<Ciphertext, CheckError> {
221 if self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
222 Ok(self.unchecked_greater_or_equal(ct_left, ct_right))
223 } else {
224 Err(CarryFull)
225 }
226 }
227
228 /// Implements the "less" (`<`) operator between two ciphertexts without checks.
229 ///
230 /// # Example
231 ///
232 ///```rust
233 /// use concrete_shortint::gen_keys;
234 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
235 ///
236 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
237 ///
238 /// let msg_1 = 1;
239 /// let msg_2 = 2;
240 ///
241 /// // Encrypt two messages
242 /// let ct_left = cks.encrypt(msg_1);
243 /// let ct_right = cks.encrypt(msg_2);
244 ///
245 /// // Do the comparison
246 /// let ct_res = sks.unchecked_less(&ct_left, &ct_right);
247 ///
248 /// // Decrypt
249 /// let res = cks.decrypt(&ct_res);
250 /// assert_eq!((msg_1 < msg_2) as u64, res);
251 /// ```
252 pub fn unchecked_less(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> Ciphertext {
253 ShortintEngine::with_thread_local_mut(|engine| {
254 engine.unchecked_less(self, ct_left, ct_right).unwrap()
255 })
256 }
257
258 /// Implements the "less" (`<`) operator between two ciphertexts with checks.
259 ///
260 /// If the operation can be performed, the result is returned in a _new_ ciphertext.
261 /// Otherwise [CheckError::CarryFull] is returned.
262 ///
263 /// # Example
264 ///
265 /// ```rust
266 /// use concrete_shortint::gen_keys;
267 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
268 ///
269 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
270 ///
271 /// let msg_1 = 1;
272 /// let msg_2 = 2;
273 ///
274 /// // Encrypt two messages:
275 /// let ct_left = cks.encrypt(msg_1);
276 /// let ct_right = cks.encrypt(msg_2);
277 ///
278 /// let res = sks.checked_less(&ct_left, &ct_right);
279 ///
280 /// assert!(res.is_ok());
281 /// let res = res.unwrap();
282 ///
283 /// let clear_res = cks.decrypt(&res);
284 /// assert_eq!((msg_1 < msg_2) as u64, clear_res);
285 /// ```
286 pub fn checked_less(
287 &self,
288 ct_left: &Ciphertext,
289 ct_right: &Ciphertext,
290 ) -> Result<Ciphertext, CheckError> {
291 if self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
292 Ok(self.unchecked_less(ct_left, ct_right))
293 } else {
294 Err(CarryFull)
295 }
296 }
297
298 /// Computes homomorphically a `<` between two ciphertexts encrypting integer values.
299 ///
300 /// This checks that the addition is possible. In the case where the carry buffers are full,
301 /// then it is automatically cleared to allow the operation.
302 /// # Example
303 ///
304 /// ```rust
305 /// use concrete_shortint::gen_keys;
306 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
307 ///
308 /// // Generate the client key and the server key:
309 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
310 ///
311 /// let msg = 1;
312 ///
313 /// // Encrypt two messages:
314 /// let mut ct1 = cks.encrypt(msg);
315 /// let mut ct2 = cks.encrypt(msg);
316 ///
317 /// // Compute homomorphically an OR:
318 /// let ct_res = sks.smart_less(&mut ct1, &mut ct2);
319 ///
320 /// // Decrypt:
321 /// let res = cks.decrypt(&ct_res);
322 /// assert_eq!((msg < msg) as u64, res);
323 /// ```
324 pub fn smart_less(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) -> Ciphertext {
325 ShortintEngine::with_thread_local_mut(|engine| {
326 engine.smart_less(self, ct_left, ct_right).unwrap()
327 })
328 }
329
330 /// Implements the "less or equal" (`<=`) between two ciphertexts operator without checks.
331 ///
332 /// # Example
333 ///
334 ///```rust
335 /// use concrete_shortint::gen_keys;
336 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
337 ///
338 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
339 ///
340 /// let msg_1 = 1;
341 /// let msg_2 = 2;
342 ///
343 /// // Encrypt two messages
344 /// let ct_left = cks.encrypt(msg_1);
345 /// let ct_right = cks.encrypt(msg_2);
346 ///
347 /// let ct_res = sks.unchecked_less_or_equal(&ct_left, &ct_right);
348 ///
349 /// // Decrypt
350 /// let res = cks.decrypt(&ct_res);
351 /// assert_eq!((msg_1 <= msg_2) as u64, res);
352 /// ```
353 pub fn unchecked_less_or_equal(
354 &self,
355 ct_left: &Ciphertext,
356 ct_right: &Ciphertext,
357 ) -> Ciphertext {
358 ShortintEngine::with_thread_local_mut(|engine| {
359 engine
360 .unchecked_less_or_equal(self, ct_left, ct_right)
361 .unwrap()
362 })
363 }
364
365 /// Implements the "less or equal" (`<=`) operator between two ciphertexts with checks.
366 ///
367 /// If the operation can be performed, the result is returned in a _new_ ciphertext.
368 /// Otherwise [CheckError::CarryFull] is returned.
369 ///
370 /// # Example
371 ///
372 /// ```rust
373 /// use concrete_shortint::gen_keys;
374 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
375 ///
376 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
377 ///
378 /// let msg_1 = 1;
379 /// let msg_2 = 2;
380 ///
381 /// // Encrypt two messages:
382 /// let ct_left = cks.encrypt(msg_1);
383 /// let ct_right = cks.encrypt(msg_2);
384 ///
385 /// let res = sks.checked_less_or_equal(&ct_left, &ct_right);
386 ///
387 /// assert!(res.is_ok());
388 /// let res = res.unwrap();
389 ///
390 /// let clear_res = cks.decrypt(&res);
391 /// assert_eq!((msg_1 <= msg_2) as u64, clear_res);
392 /// ```
393 pub fn checked_less_or_equal(
394 &self,
395 ct_left: &Ciphertext,
396 ct_right: &Ciphertext,
397 ) -> Result<Ciphertext, CheckError> {
398 if self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
399 Ok(self.unchecked_less(ct_left, ct_right))
400 } else {
401 Err(CarryFull)
402 }
403 }
404
405 /// Computes homomorphically a `<=` between two ciphertexts encrypting integer values.
406 ///
407 /// This checks that the addition is possible. In the case where the carry buffers are full,
408 /// then it is automatically cleared to allow the operation.
409 /// # Example
410 ///
411 /// ```rust
412 /// use concrete_shortint::gen_keys;
413 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
414 ///
415 /// // Generate the client key and the server key:
416 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
417 ///
418 /// let msg = 1;
419 ///
420 /// // Encrypt two messages:
421 /// let mut ct1 = cks.encrypt(msg);
422 /// let mut ct2 = cks.encrypt(msg);
423 ///
424 /// // Compute homomorphically an OR:
425 /// let ct_res = sks.smart_less_or_equal(&mut ct1, &mut ct2);
426 ///
427 /// // Decrypt:
428 /// let res = cks.decrypt(&ct_res);
429 /// assert_eq!((msg >= msg) as u64, res);
430 /// ```
431 pub fn smart_less_or_equal(
432 &self,
433 ct_left: &mut Ciphertext,
434 ct_right: &mut Ciphertext,
435 ) -> Ciphertext {
436 ShortintEngine::with_thread_local_mut(|engine| {
437 engine.smart_less_or_equal(self, ct_left, ct_right).unwrap()
438 })
439 }
440
441 /// Implements the "equal" operator (`==`) between two ciphertexts without checks.
442 ///
443 /// # Example
444 ///
445 ///```rust
446 /// use concrete_shortint::gen_keys;
447 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
448 ///
449 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
450 ///
451 /// let msg_1 = 2;
452 /// let msg_2 = 2;
453 ///
454 /// // Encrypt two messages
455 /// let ct_left = cks.encrypt(msg_1);
456 /// let ct_right = cks.encrypt(msg_2);
457 ///
458 /// let ct_res = sks.unchecked_equal(&ct_left, &ct_right);
459 ///
460 /// // Decrypt
461 /// let res = cks.decrypt(&ct_res);
462 /// assert_eq!(res, 1);
463 /// ```
464 pub fn unchecked_equal(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> Ciphertext {
465 ShortintEngine::with_thread_local_mut(|engine| {
466 engine.unchecked_equal(self, ct_left, ct_right).unwrap()
467 })
468 }
469
470 /// Implements the "less" (`==`) operator between two ciphertexts with checks.
471 ///
472 /// If the operation can be performed, the result is returned in a _new_ ciphertext.
473 /// Otherwise [CheckError::CarryFull] is returned.
474 ///
475 /// # Example
476 ///
477 /// ```rust
478 /// use concrete_shortint::gen_keys;
479 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
480 ///
481 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
482 ///
483 /// let msg_1 = 1;
484 /// let msg_2 = 2;
485 ///
486 /// // Encrypt two messages:
487 /// let ct_left = cks.encrypt(msg_1);
488 /// let ct_right = cks.encrypt(msg_2);
489 ///
490 /// let res = sks.checked_equal(&ct_left, &ct_right);
491 ///
492 /// assert!(res.is_ok());
493 /// let res = res.unwrap();
494 ///
495 /// let clear_res = cks.decrypt(&res);
496 /// assert_eq!((msg_1 == msg_2) as u64, clear_res);
497 /// ```
498 pub fn checked_equal(
499 &self,
500 ct_left: &Ciphertext,
501 ct_right: &Ciphertext,
502 ) -> Result<Ciphertext, CheckError> {
503 if self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
504 Ok(self.unchecked_equal(ct_left, ct_right))
505 } else {
506 Err(CarryFull)
507 }
508 }
509
510 /// Computes homomorphically a `==` between two ciphertexts encrypting integer values.
511 ///
512 /// This checks that the addition is possible. In the case where the carry buffers are full,
513 /// then it is automatically cleared to allow the operation.
514 /// # Example
515 ///
516 /// ```rust
517 /// use concrete_shortint::gen_keys;
518 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
519 ///
520 /// // Generate the client key and the server key:
521 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
522 ///
523 /// let msg = 1;
524 ///
525 /// // Encrypt two messages:
526 /// let mut ct1 = cks.encrypt(msg);
527 /// let mut ct2 = cks.encrypt(msg);
528 ///
529 /// // Compute homomorphically an OR:
530 /// let ct_res = sks.smart_equal(&mut ct1, &mut ct2);
531 ///
532 /// // Decrypt:
533 /// let res = cks.decrypt(&ct_res);
534 /// assert_eq!((msg == msg) as u64, res);
535 /// ```
536 pub fn smart_equal(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) -> Ciphertext {
537 ShortintEngine::with_thread_local_mut(|engine| {
538 engine.smart_equal(self, ct_left, ct_right).unwrap()
539 })
540 }
541
542 /// Implements the "equal" operator (`==`) between a ciphertext and a scalar without checks.
543 ///
544 /// # Example
545 ///
546 ///```rust
547 /// use concrete_shortint::gen_keys;
548 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
549 ///
550 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
551 ///
552 /// let msg_1 = 2;
553 /// let scalar = 2;
554 ///
555 /// // Encrypt two messages
556 /// let ct_left = cks.encrypt(msg_1);
557 ///
558 /// let ct_res = sks.smart_scalar_equal(&ct_left, scalar);
559 ///
560 /// // Decrypt
561 /// let res = cks.decrypt(&ct_res);
562 /// assert_eq!(res, (msg_1 == scalar as u64) as u64);
563 /// ```
564 pub fn smart_scalar_equal(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
565 ShortintEngine::with_thread_local_mut(|engine| {
566 engine.smart_scalar_equal(self, ct_left, scalar).unwrap()
567 })
568 }
569
570 /// Implements the "equal" operator (`>=`) between a ciphertext and a scalar without checks.
571 ///
572 /// # Example
573 ///
574 ///```rust
575 /// use concrete_shortint::gen_keys;
576 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
577 ///
578 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
579 ///
580 /// let msg_1 = 2;
581 /// let scalar = 2;
582 ///
583 /// // Encrypt two messages
584 /// let ct_left = cks.encrypt(msg_1);
585 ///
586 /// let ct_res = sks.smart_scalar_greater_or_equal(&ct_left, scalar);
587 ///
588 /// // Decrypt
589 /// let res = cks.decrypt(&ct_res);
590 /// assert_eq!(res, (msg_1 >= scalar as u64) as u64);
591 /// ```
592 pub fn smart_scalar_greater_or_equal(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
593 ShortintEngine::with_thread_local_mut(|engine| {
594 engine
595 .smart_scalar_greater_or_equal(self, ct_left, scalar)
596 .unwrap()
597 })
598 }
599
600 /// Implements the "less or equal" operator (`<=`) between a ciphertext and a scalar without
601 /// checks.
602 ///
603 /// # Example
604 ///
605 ///```rust
606 /// use concrete_shortint::gen_keys;
607 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
608 ///
609 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
610 ///
611 /// let msg_1 = 2;
612 /// let scalar = 2;
613 ///
614 /// // Encrypt two messages
615 /// let ct_left = cks.encrypt(msg_1);
616 ///
617 /// let ct_res = sks.smart_scalar_less_or_equal(&ct_left, scalar);
618 ///
619 /// // Decrypt
620 /// let res = cks.decrypt(&ct_res);
621 /// assert_eq!(res, (msg_1 <= scalar as u64) as u64);
622 /// ```
623 pub fn smart_scalar_less_or_equal(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
624 ShortintEngine::with_thread_local_mut(|engine| {
625 engine
626 .smart_scalar_less_or_equal(self, ct_left, scalar)
627 .unwrap()
628 })
629 }
630
631 /// Implements the "equal" operator (`>`) between a ciphertext and a scalar without checks.
632 ///
633 /// # Example
634 ///
635 ///```rust
636 /// use concrete_shortint::gen_keys;
637 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
638 ///
639 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
640 ///
641 /// let msg_1 = 2;
642 /// let scalar = 2;
643 ///
644 /// // Encrypt two messages
645 /// let ct_left = cks.encrypt(msg_1);
646 ///
647 /// let ct_res = sks.smart_scalar_greater(&ct_left, scalar);
648 ///
649 /// // Decrypt
650 /// let res = cks.decrypt(&ct_res);
651 /// assert_eq!(res, (msg_1 > scalar as u64) as u64);
652 /// ```
653 pub fn smart_scalar_greater(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
654 ShortintEngine::with_thread_local_mut(|engine| {
655 engine.smart_scalar_greater(self, ct_left, scalar).unwrap()
656 })
657 }
658
659 /// Implements the "less" operator (`<`) between a ciphertext and a scalar without checks.
660 ///
661 /// # Example
662 ///
663 ///```rust
664 /// use concrete_shortint::gen_keys;
665 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
666 ///
667 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);
668 ///
669 /// let msg_1 = 2;
670 /// let scalar = 2;
671 ///
672 /// // Encrypt two messages
673 /// let ct_left = cks.encrypt(msg_1);
674 ///
675 /// let ct_res = sks.smart_scalar_less(&ct_left, scalar);
676 ///
677 /// // Decrypt
678 /// let res = cks.decrypt(&ct_res);
679 /// assert_eq!(res, (msg_1 < scalar as u64) as u64);
680 /// ```
681 pub fn smart_scalar_less(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext {
682 ShortintEngine::with_thread_local_mut(|engine| {
683 engine.smart_scalar_less(self, ct_left, scalar).unwrap()
684 })
685 }
686}