concrete_integer/server_key/crt/mod.rs
1use crate::ciphertext::CrtCiphertext;
2use crate::ServerKey;
3
4#[cfg(test)]
5mod tests;
6
7mod add_crt;
8mod mul_crt;
9mod neg_crt;
10mod scalar_add_crt;
11mod scalar_mul_crt;
12mod scalar_sub_crt;
13mod sub_crt;
14
15impl ServerKey {
16 /// Extract all the messages.
17 ///
18 /// # Example
19 ///
20 ///```rust
21 /// use concrete_integer::gen_keys;
22 /// use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
23 ///
24 /// // Generate the client key and the server key:
25 /// let (cks, sks) = gen_keys(&PARAM_MESSAGE_2_CARRY_2);
26 ///
27 /// let clear_1 = 14;
28 /// let clear_2 = 14;
29 /// let basis = vec![2, 3, 5];
30 /// // Encrypt two messages
31 /// let mut ctxt_1 = cks.encrypt_crt(clear_1, basis.clone());
32 /// let ctxt_2 = cks.encrypt_crt(clear_2, basis);
33 ///
34 /// // Compute homomorphically a multiplication
35 /// sks.unchecked_crt_add_assign(&mut ctxt_1, &ctxt_2);
36 ///
37 /// sks.full_extract(&mut ctxt_1);
38 ///
39 /// // Decrypt
40 /// let res = cks.decrypt_crt(&ctxt_1);
41 /// assert_eq!((clear_1 + clear_2) % 30, res);
42 /// ```
43 pub fn full_extract(&self, ctxt: &mut CrtCiphertext) {
44 for ct_i in ctxt.blocks.iter_mut() {
45 self.key.message_extract_assign(ct_i);
46 }
47 }
48
49 /// Computes a PBS for CRT-compliant functions.
50 ///
51 /// # Warning
52 /// This allows to compute programmable bootstrapping over integers under the condition that
53 /// the function is said to be CRT-compliant. This means that the function should be correct
54 /// when evaluated on each modular block independently (e.g. arithmetic functions).
55 ///
56 /// # Example
57 ///
58 /// ```rust
59 /// use concrete_integer::gen_keys_crt;
60 /// use concrete_shortint::parameters::DEFAULT_PARAMETERS;
61 ///
62 /// // Generate the client key and the server key:
63 /// let basis = vec![2, 3, 5];
64 /// let (cks, sks) = gen_keys_crt(&DEFAULT_PARAMETERS, basis);
65 ///
66 /// let clear_1 = 28;
67 ///
68 /// let mut ctxt_1 = cks.encrypt(clear_1);
69 ///
70 /// // Compute homomorphically the crt-compliant PBS
71 /// sks.pbs_crt_compliant_function_assign(&mut ctxt_1, |x| x * x * x);
72 ///
73 /// // Decrypt
74 /// let res = cks.decrypt(&ctxt_1);
75 /// assert_eq!((clear_1 * clear_1 * clear_1) % 30, res);
76 /// ```
77 pub fn pbs_crt_compliant_function_assign<F>(&self, ct1: &mut CrtCiphertext, f: F)
78 where
79 F: Fn(u64) -> u64,
80 {
81 let basis = &ct1.moduli;
82
83 let accumulators = basis
84 .iter()
85 .copied()
86 .map(|b| self.key.generate_accumulator(|x| f(x) % b));
87
88 for (block, acc) in ct1.blocks.iter_mut().zip(accumulators) {
89 self.key
90 .keyswitch_programmable_bootstrap_assign(block, &acc);
91 }
92 }
93
94 pub fn pbs_crt_compliant_function<F>(&self, ct1: &mut CrtCiphertext, f: F) -> CrtCiphertext
95 where
96 F: Fn(u64) -> u64,
97 {
98 let mut ct_res = ct1.clone();
99 self.pbs_crt_compliant_function_assign(&mut ct_res, f);
100 ct_res
101 }
102}