concrete_integer/server_key/crt_parallel/sub_crt.rs
1use crate::{CrtCiphertext, ServerKey};
2
3impl ServerKey {
4 /// Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
5 ///
6 /// This function computes the subtraction without checking if it exceeds the capacity of the
7 /// ciphertext.
8 ///
9 /// The result is returned as a new ciphertext.
10 /// # Example
11 ///
12 ///```rust
13 /// use concrete_integer::gen_keys;
14 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
15 ///
16 /// // Generate the client key and the server key:
17 /// let (cks, sks) = gen_keys(&PARAM_MESSAGE_2_CARRY_2);
18 ///
19 /// let clear_1 = 14;
20 /// let clear_2 = 5;
21 /// let basis = vec![2, 3, 5];
22 /// // Encrypt two messages
23 /// let mut ctxt_1 = cks.encrypt_crt(clear_1, basis.clone());
24 /// let mut ctxt_2 = cks.encrypt_crt(clear_2, basis.clone());
25 ///
26 /// let ctxt = sks.unchecked_crt_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
27 ///
28 /// // Decrypt
29 /// let res = cks.decrypt_crt(&ctxt);
30 /// assert_eq!((clear_1 - clear_2) % 30, res);
31 /// ```
32 pub fn unchecked_crt_sub_parallelized(
33 &self,
34 ctxt_left: &CrtCiphertext,
35 ctxt_right: &CrtCiphertext,
36 ) -> CrtCiphertext {
37 let mut result = ctxt_left.clone();
38 self.unchecked_crt_sub_assign_parallelized(&mut result, ctxt_right);
39 result
40 }
41
42 /// Computes homomorphically a subtraction between two ciphertexts encrypting integer values.
43 ///
44 /// This function computes the subtraction without checking if it exceeds the capacity of the
45 /// ciphertext.
46 ///
47 /// The result is assigned to the `ct_left` ciphertext.
48 /// # Example
49 ///
50 ///```rust
51 /// use concrete_integer::gen_keys;
52 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
53 ///
54 /// // Generate the client key and the server key:
55 /// let (cks, sks) = gen_keys(&PARAM_MESSAGE_2_CARRY_2);
56 ///
57 /// let clear_1 = 14;
58 /// let clear_2 = 5;
59 /// let basis = vec![2, 3, 5];
60 /// // Encrypt two messages
61 /// let mut ctxt_1 = cks.encrypt_crt(clear_1, basis.clone());
62 /// let mut ctxt_2 = cks.encrypt_crt(clear_2, basis.clone());
63 ///
64 /// let ctxt = sks.unchecked_crt_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
65 ///
66 /// // Decrypt
67 /// let res = cks.decrypt_crt(&ctxt);
68 /// assert_eq!((clear_1 - clear_2) % 30, res);
69 /// ```
70 pub fn unchecked_crt_sub_assign_parallelized(
71 &self,
72 ctxt_left: &mut CrtCiphertext,
73 ctxt_right: &CrtCiphertext,
74 ) {
75 let neg = self.unchecked_crt_neg_parallelized(ctxt_right);
76 self.unchecked_crt_add_assign_parallelized(ctxt_left, &neg);
77 }
78
79 /// Computes homomorphically the subtraction between ct_left and ct_right.
80 ///
81 /// # Example
82 ///
83 ///```rust
84 /// use concrete_integer::gen_keys;
85 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
86 ///
87 /// // Generate the client key and the server key:
88 /// let (cks, sks) = gen_keys(&PARAM_MESSAGE_2_CARRY_2);
89 ///
90 /// let clear_1 = 14;
91 /// let clear_2 = 5;
92 /// let basis = vec![2, 3, 5];
93 /// // Encrypt two messages
94 /// let mut ctxt_1 = cks.encrypt_crt(clear_1, basis.clone());
95 /// let mut ctxt_2 = cks.encrypt_crt(clear_2, basis.clone());
96 ///
97 /// let ctxt = sks.smart_crt_sub_parallelized(&mut ctxt_1, &mut ctxt_2);
98 ///
99 /// // Decrypt
100 /// let res = cks.decrypt_crt(&ctxt);
101 /// assert_eq!((clear_1 - clear_2) % 30, res);
102 /// ```
103 pub fn smart_crt_sub_parallelized(
104 &self,
105 ctxt_left: &mut CrtCiphertext,
106 ctxt_right: &mut CrtCiphertext,
107 ) -> CrtCiphertext {
108 // If the ciphertext cannot be added together without exceeding the capacity of a ciphertext
109 if !self.is_crt_sub_possible(ctxt_left, ctxt_right) {
110 rayon::join(
111 || self.full_extract_parallelized(ctxt_left),
112 || self.full_extract_parallelized(ctxt_right),
113 );
114 }
115
116 self.unchecked_crt_sub_parallelized(ctxt_left, ctxt_right)
117 }
118
119 /// Computes homomorphically the subtraction between ct_left and ct_right.
120 ///
121 /// # Example
122 ///
123 ///```rust
124 /// use concrete_integer::gen_keys;
125 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
126 ///
127 /// // Generate the client key and the server key:
128 /// let (cks, sks) = gen_keys(&PARAM_MESSAGE_2_CARRY_2);
129 ///
130 /// let clear_1 = 14;
131 /// let clear_2 = 5;
132 /// let basis = vec![2, 3, 5];
133 /// // Encrypt two messages
134 /// let mut ctxt_1 = cks.encrypt_crt(clear_1, basis.clone());
135 /// let mut ctxt_2 = cks.encrypt_crt(clear_2, basis.clone());
136 ///
137 /// sks.smart_crt_sub_assign_parallelized(&mut ctxt_1, &mut ctxt_2);
138 ///
139 /// // Decrypt
140 /// let res = cks.decrypt_crt(&ctxt_1);
141 /// assert_eq!((clear_1 - clear_2) % 30, res);
142 /// ```
143 pub fn smart_crt_sub_assign_parallelized(
144 &self,
145 ctxt_left: &mut CrtCiphertext,
146 ctxt_right: &mut CrtCiphertext,
147 ) {
148 // If the ciphertext cannot be added together without exceeding the capacity of a ciphertext
149 if !self.is_crt_sub_possible(ctxt_left, ctxt_right) {
150 rayon::join(
151 || self.full_extract_parallelized(ctxt_left),
152 || self.full_extract_parallelized(ctxt_right),
153 );
154 }
155
156 self.unchecked_crt_sub_assign_parallelized(ctxt_left, ctxt_right);
157 }
158}