poulpy_core/decryption/
lwe_ct.rs

1use poulpy_hal::{
2    api::{ScratchOwnedAlloc, ScratchOwnedBorrow, ZnNormalizeInplace},
3    layouts::{Backend, DataMut, DataRef, Module, ScratchOwned, ZnxView, ZnxViewMut},
4    oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl},
5};
6
7use crate::layouts::{LWECiphertext, LWEInfos, LWEPlaintext, LWESecret};
8
9impl<DataSelf> LWECiphertext<DataSelf>
10where
11    DataSelf: DataRef,
12{
13    pub fn decrypt<DataPt, DataSk, B>(&self, module: &Module<B>, pt: &mut LWEPlaintext<DataPt>, sk: &LWESecret<DataSk>)
14    where
15        DataPt: DataMut,
16        DataSk: DataRef,
17        Module<B>: ZnNormalizeInplace<B>,
18        B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
19    {
20        #[cfg(debug_assertions)]
21        {
22            assert_eq!(self.n(), sk.n());
23        }
24
25        (0..pt.size().min(self.size())).for_each(|i| {
26            pt.data.at_mut(0, i)[0] = self.data.at(0, i)[0]
27                + self.data.at(0, i)[1..]
28                    .iter()
29                    .zip(sk.data.at(0, 0))
30                    .map(|(x, y)| x * y)
31                    .sum::<i64>();
32        });
33        module.zn_normalize_inplace(
34            1,
35            self.base2k().into(),
36            &mut pt.data,
37            0,
38            ScratchOwned::alloc(size_of::<i64>()).borrow(),
39        );
40        pt.base2k = self.base2k();
41        pt.k = crate::layouts::TorusPrecision(self.k().0.min(pt.size() as u32 * self.base2k().0));
42    }
43}