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}