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}