concrete_integer/server_key/radix_parallel/
bitwise_op.rs

1use crate::ciphertext::RadixCiphertext;
2use crate::ServerKey;
3
4impl ServerKey {
5    /// Computes homomorphically a bitand between two ciphertexts encrypting integer values.
6    ///
7    /// # Warning
8    ///
9    /// - Multithreaded
10    ///
11    /// # Example
12    ///
13    /// ```rust
14    /// use concrete_integer::gen_keys_radix;
15    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
16    ///
17    /// // Generate the client key and the server key:
18    /// let num_blocks = 4;
19    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
20    ///
21    /// let msg1 = 14;
22    /// let msg2 = 97;
23    ///
24    /// let mut ct1 = cks.encrypt(msg1);
25    /// let mut ct2 = cks.encrypt(msg2);
26    ///
27    /// let ct_res = sks.smart_bitand_parallelized(&mut ct1, &mut ct2);
28    ///
29    /// // Decrypt:
30    /// let dec_result = cks.decrypt(&ct_res);
31    /// assert_eq!(dec_result, msg1 & msg2);
32    /// ```
33    pub fn smart_bitand_parallelized(
34        &self,
35        ct_left: &mut RadixCiphertext,
36        ct_right: &mut RadixCiphertext,
37    ) -> RadixCiphertext {
38        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
39            rayon::join(
40                || self.full_propagate_parallelized(ct_left),
41                || self.full_propagate_parallelized(ct_right),
42            );
43        }
44        self.unchecked_bitand(ct_left, ct_right)
45    }
46
47    pub fn smart_bitand_assign_parallelized(
48        &self,
49        ct_left: &mut RadixCiphertext,
50        ct_right: &mut RadixCiphertext,
51    ) {
52        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
53            rayon::join(
54                || self.full_propagate_parallelized(ct_left),
55                || self.full_propagate_parallelized(ct_right),
56            );
57        }
58        self.unchecked_bitand_assign(ct_left, ct_right);
59    }
60
61    /// Computes homomorphically a bitor between two ciphertexts encrypting integer values.
62    ///
63    /// # Warning
64    ///
65    /// - Multithreaded
66    ///
67    /// # Example
68    ///
69    /// ```rust
70    /// use concrete_integer::gen_keys_radix;
71    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
72    ///
73    /// // Generate the client key and the server key:
74    /// let num_blocks = 4;
75    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
76    ///
77    /// let msg1 = 14;
78    /// let msg2 = 97;
79    ///
80    /// let mut ct1 = cks.encrypt(msg1);
81    /// let mut ct2 = cks.encrypt(msg2);
82    ///
83    /// let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);
84    ///
85    /// // Decrypt:
86    /// let dec_result = cks.decrypt(&ct_res);
87    /// assert_eq!(dec_result, msg1 | msg2);
88    /// ```
89    pub fn smart_bitor_parallelized(
90        &self,
91        ct_left: &mut RadixCiphertext,
92        ct_right: &mut RadixCiphertext,
93    ) -> RadixCiphertext {
94        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
95            rayon::join(
96                || self.full_propagate_parallelized(ct_left),
97                || self.full_propagate_parallelized(ct_right),
98            );
99        }
100        self.unchecked_bitor(ct_left, ct_right)
101    }
102
103    pub fn smart_bitor_assign_parallelized(
104        &self,
105        ct_left: &mut RadixCiphertext,
106        ct_right: &mut RadixCiphertext,
107    ) {
108        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
109            rayon::join(
110                || self.full_propagate_parallelized(ct_left),
111                || self.full_propagate_parallelized(ct_right),
112            );
113        }
114        self.unchecked_bitor_assign(ct_left, ct_right);
115    }
116
117    /// Computes homomorphically a bitxor between two ciphertexts encrypting integer values.
118    ///
119    /// # Warning
120    ///
121    /// - Multithreaded
122    ///
123    /// # Example
124    ///
125    /// ```rust
126    /// use concrete_integer::gen_keys_radix;
127    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
128    ///
129    /// // Generate the client key and the server key:
130    /// let num_blocks = 4;
131    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
132    ///
133    /// let msg1 = 14;
134    /// let msg2 = 97;
135    ///
136    /// let mut ct1 = cks.encrypt(msg1);
137    /// let mut ct2 = cks.encrypt(msg2);
138    ///
139    /// let ct_res = sks.smart_bitxor_parallelized(&mut ct1, &mut ct2);
140    ///
141    /// // Decrypt:
142    /// let dec_result = cks.decrypt(&ct_res);
143    /// assert_eq!(dec_result, msg1 ^ msg2);
144    /// ```
145    pub fn smart_bitxor_parallelized(
146        &self,
147        ct_left: &mut RadixCiphertext,
148        ct_right: &mut RadixCiphertext,
149    ) -> RadixCiphertext {
150        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
151            rayon::join(
152                || self.full_propagate_parallelized(ct_left),
153                || self.full_propagate_parallelized(ct_right),
154            );
155        }
156        self.unchecked_bitxor(ct_left, ct_right)
157    }
158
159    pub fn smart_bitxor_assign_parallelized(
160        &self,
161        ct_left: &mut RadixCiphertext,
162        ct_right: &mut RadixCiphertext,
163    ) {
164        if !self.is_functional_bivariate_pbs_possible(ct_left, ct_right) {
165            rayon::join(
166                || self.full_propagate_parallelized(ct_left),
167                || self.full_propagate_parallelized(ct_right),
168            );
169        }
170        self.unchecked_bitxor_assign(ct_left, ct_right);
171    }
172}