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