concrete_integer/server_key/radix/
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
11use super::ServerKey;
12
13use crate::RadixCiphertext;
14
15#[cfg(test)]
16mod tests;
17
18impl ServerKey {
19    /// Create a ciphertext filled with zeros
20    ///
21    /// # Example
22    ///
23    /// ```rust
24    /// use concrete_integer::gen_keys_radix;
25    /// use concrete_shortint::parameters::DEFAULT_PARAMETERS;
26    ///
27    /// let num_blocks = 4;
28    ///
29    /// // Generate the client key and the server key:
30    /// let (cks, sks) = gen_keys_radix(&DEFAULT_PARAMETERS, num_blocks);
31    ///
32    /// let ctxt = sks.create_trivial_zero_radix(num_blocks);
33    ///
34    /// // Decrypt:
35    /// let dec = cks.decrypt(&ctxt);
36    /// assert_eq!(0, dec);
37    /// ```
38    pub fn create_trivial_zero_radix(&self, num_blocks: usize) -> RadixCiphertext {
39        let mut vec_res = Vec::with_capacity(num_blocks);
40        for _ in 0..num_blocks {
41            vec_res.push(self.key.create_trivial(0_u8));
42        }
43
44        RadixCiphertext { blocks: vec_res }
45    }
46
47    /// Propagate the carry of the 'index' block to the next one.
48    ///
49    /// # Example
50    ///
51    ///```rust
52    /// use concrete_integer::gen_keys_radix;
53    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
54    ///
55    /// let num_blocks = 4;
56    ///
57    /// // Generate the client key and the server key:
58    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
59    ///
60    /// let msg = 7;
61    ///
62    /// let ct1 = cks.encrypt(msg);
63    /// let ct2 = cks.encrypt(msg);
64    ///
65    /// // Compute homomorphically an addition:
66    /// let mut ct_res = sks.unchecked_add(&ct1, &ct2);
67    /// sks.propagate(&mut ct_res, 0);
68    ///
69    /// // Decrypt one block:
70    /// let res = cks.decrypt_one_block(&ct_res.blocks()[1]);
71    /// assert_eq!(3, res);
72    /// ```
73    pub fn propagate(&self, ctxt: &mut RadixCiphertext, index: usize) {
74        let carry = self.key.carry_extract(&ctxt.blocks[index]);
75
76        ctxt.blocks[index] = self.key.message_extract(&ctxt.blocks[index]);
77
78        //add the carry to the next block
79        if index < ctxt.blocks.len() - 1 {
80            self.key
81                .unchecked_add_assign(&mut ctxt.blocks[index + 1], &carry);
82        }
83    }
84
85    /// Propagate all the carries.
86    ///
87    /// # Example
88    ///
89    ///```rust
90    /// use concrete_integer::gen_keys_radix;
91    /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
92    ///
93    /// let num_blocks = 4;
94    ///
95    /// // Generate the client key and the server key:
96    /// let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, num_blocks);
97    ///
98    /// let msg = 10;
99    ///
100    /// let mut ct1 = cks.encrypt(msg);
101    /// let mut ct2 = cks.encrypt(msg);
102    ///
103    /// // Compute homomorphically an addition:
104    /// let mut ct_res = sks.unchecked_add(&mut ct1, &mut ct2);
105    /// sks.full_propagate(&mut ct_res);
106    ///
107    /// // Decrypt:
108    /// let res = cks.decrypt(&ct_res);
109    /// assert_eq!(msg + msg, res);
110    /// ```
111    pub fn full_propagate(&self, ctxt: &mut RadixCiphertext) {
112        let len = ctxt.blocks.len();
113        for i in 0..len {
114            self.propagate(ctxt, i);
115        }
116    }
117}