concrete_core/backends/default/implementation/engines/default_engine/lwe_ciphertext_fusing_addition.rs
1use crate::backends::default::implementation::engines::DefaultEngine;
2use crate::backends::default::implementation::entities::{LweCiphertext32, LweCiphertext64};
3use crate::specification::engines::{
4 LweCiphertextFusingAdditionEngine, LweCiphertextFusingAdditionError,
5};
6
7/// # Description:
8/// Implementation of [`LweCiphertextFusingAdditionEngine`] for [`DefaultEngine`] that operates on
9/// 32 bits integers.
10impl LweCiphertextFusingAdditionEngine<LweCiphertext32, LweCiphertext32> for DefaultEngine {
11 /// # Example:
12 /// ```
13 /// use concrete_core::prelude::{LweDimension, Variance, *};
14 /// # use std::error::Error;
15 ///
16 /// # fn main() -> Result<(), Box<dyn Error>> {
17 /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
18 /// let lwe_dimension = LweDimension(2);
19 /// // Here a hard-set encoding is applied (shift by 20 bits)
20 /// let input_1 = 3_u32 << 20;
21 /// let input_2 = 5_u32 << 20;
22 /// let noise = Variance(2_f64.powf(-25.));
23 ///
24 /// // Unix seeder must be given a secret input.
25 /// // Here we just give it 0, which is totally unsafe.
26 /// const UNSAFE_SECRET: u128 = 0;
27 /// let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
28 /// let key: LweSecretKey32 = engine.generate_new_lwe_secret_key(lwe_dimension)?;
29 /// let plaintext_1 = engine.create_plaintext_from(&input_1)?;
30 /// let plaintext_2 = engine.create_plaintext_from(&input_2)?;
31 /// let ciphertext_1 = engine.encrypt_lwe_ciphertext(&key, &plaintext_1, noise)?;
32 /// let mut ciphertext_2 = engine.encrypt_lwe_ciphertext(&key, &plaintext_2, noise)?;
33 ///
34 /// engine.fuse_add_lwe_ciphertext(&mut ciphertext_2, &ciphertext_1)?;
35 /// #
36 /// assert_eq!(ciphertext_2.lwe_dimension(), lwe_dimension);
37 ///
38 /// #
39 /// # Ok(())
40 /// # }
41 /// ```
42 fn fuse_add_lwe_ciphertext(
43 &mut self,
44 output: &mut LweCiphertext32,
45 input: &LweCiphertext32,
46 ) -> Result<(), LweCiphertextFusingAdditionError<Self::EngineError>> {
47 LweCiphertextFusingAdditionError::perform_generic_checks(output, input)?;
48 unsafe { self.fuse_add_lwe_ciphertext_unchecked(output, input) };
49 Ok(())
50 }
51
52 unsafe fn fuse_add_lwe_ciphertext_unchecked(
53 &mut self,
54 output: &mut LweCiphertext32,
55 input: &LweCiphertext32,
56 ) {
57 output.0.update_with_add(&input.0);
58 }
59}
60
61/// # Description:
62/// Implementation of [`LweCiphertextFusingAdditionEngine`] for [`DefaultEngine`] that operates on
63/// 64 bits integers.
64impl LweCiphertextFusingAdditionEngine<LweCiphertext64, LweCiphertext64> for DefaultEngine {
65 /// # Example:
66 /// ```
67 /// use concrete_core::prelude::{LweDimension, Variance, *};
68 /// # use std::error::Error;
69 ///
70 /// # fn main() -> Result<(), Box<dyn Error>> {
71 /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
72 /// let lwe_dimension = LweDimension(2);
73 /// // Here a hard-set encoding is applied (shift by 50 bits)
74 /// let input_1 = 3_u64 << 50;
75 /// let input_2 = 5_u64 << 50;
76 /// let noise = Variance(2_f64.powf(-25.));
77 ///
78 /// // Unix seeder must be given a secret input.
79 /// // Here we just give it 0, which is totally unsafe.
80 /// const UNSAFE_SECRET: u128 = 0;
81 /// let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
82 /// let key: LweSecretKey64 = engine.generate_new_lwe_secret_key(lwe_dimension)?;
83 /// let plaintext_1 = engine.create_plaintext_from(&input_1)?;
84 /// let plaintext_2 = engine.create_plaintext_from(&input_2)?;
85 /// let ciphertext_1 = engine.encrypt_lwe_ciphertext(&key, &plaintext_1, noise)?;
86 /// let mut ciphertext_2 = engine.encrypt_lwe_ciphertext(&key, &plaintext_2, noise)?;
87 ///
88 /// engine.fuse_add_lwe_ciphertext(&mut ciphertext_2, &ciphertext_1)?;
89 /// #
90 /// assert_eq!(ciphertext_2.lwe_dimension(), lwe_dimension);
91 ///
92 /// #
93 /// # Ok(())
94 /// # }
95 /// ```
96 fn fuse_add_lwe_ciphertext(
97 &mut self,
98 output: &mut LweCiphertext64,
99 input: &LweCiphertext64,
100 ) -> Result<(), LweCiphertextFusingAdditionError<Self::EngineError>> {
101 LweCiphertextFusingAdditionError::perform_generic_checks(output, input)?;
102 unsafe { self.fuse_add_lwe_ciphertext_unchecked(output, input) };
103 Ok(())
104 }
105
106 unsafe fn fuse_add_lwe_ciphertext_unchecked(
107 &mut self,
108 output: &mut LweCiphertext64,
109 input: &LweCiphertext64,
110 ) {
111 output.0.update_with_add(&input.0);
112 }
113}