concrete_integer/server_key/radix_parallel/
mod.rs

1mod add;
2mod bitwise_op;
3mod mul;
4mod neg;
5mod scalar_add;
6mod scalar_mul;
7mod scalar_sub;
8mod shift;
9mod sub;
10
11#[cfg(test)]
12mod tests;
13
14use super::ServerKey;
15use crate::RadixCiphertext;
16
17// parallelized versions
18impl ServerKey {
19    /// Propagate the carry of the 'index' block to the next one.
20    ///
21    /// # Example
22    ///
23    ///```rust
24    /// use concrete_integer::gen_keys_radix;
25    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
26    ///
27    /// // Generate the client key and the server key:
28    /// let num_blocks = 4;
29    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
30    ///
31    /// let msg = 7;
32    ///
33    /// let ct1 = cks.encrypt(msg);
34    /// let ct2 = cks.encrypt(msg);
35    ///
36    /// // Compute homomorphically an addition:
37    /// let mut ct_res = sks.unchecked_add(&ct1, &ct2);
38    /// sks.propagate_parallelized(&mut ct_res, 0);
39    ///
40    /// // Decrypt one block:
41    /// let res = cks.decrypt_one_block(&ct_res.blocks()[1]);
42    /// assert_eq!(3, res);
43    /// ```
44    pub fn propagate_parallelized(&self, ctxt: &mut RadixCiphertext, index: usize) {
45        let (carry, message) = rayon::join(
46            || self.key.carry_extract(&ctxt.blocks[index]),
47            || self.key.message_extract(&ctxt.blocks[index]),
48        );
49        ctxt.blocks[index] = message;
50
51        //add the carry to the next block
52        if index < ctxt.blocks.len() - 1 {
53            self.key
54                .unchecked_add_assign(&mut ctxt.blocks[index + 1], &carry);
55        }
56    }
57
58    /// Propagate all the carries.
59    ///
60    /// # Example
61    ///
62    ///```rust
63    /// use concrete_integer::gen_keys_radix;
64    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
65    ///
66    /// // Generate the client key and the server key:
67    /// let num_blocks = 4;
68    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
69    ///
70    /// let msg = 10;
71    ///
72    /// let mut ct1 = cks.encrypt(msg);
73    /// let mut ct2 = cks.encrypt(msg);
74    ///
75    /// // Compute homomorphically an addition:
76    /// let mut ct_res = sks.unchecked_add(&mut ct1, &mut ct2);
77    /// sks.full_propagate_parallelized(&mut ct_res);
78    ///
79    /// // Decrypt:
80    /// let res = cks.decrypt(&ct_res);
81    /// assert_eq!(msg + msg, res);
82    /// ```
83    pub fn full_propagate_parallelized(&self, ctxt: &mut RadixCiphertext) {
84        let len = ctxt.blocks.len();
85        for i in 0..len {
86            self.propagate_parallelized(ctxt, i);
87        }
88    }
89}