Skip to main content

poulpy_core/layouts/prepared/
glwe_secret.rs

1use poulpy_hal::{
2    api::{SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare},
3    layouts::{Backend, Data, Module, SvpPPol, SvpPPolToBackendMut, SvpPPolToBackendRef, ZnxInfos},
4};
5
6use crate::{
7    GetDistribution, GetDistributionMut,
8    dist::Distribution,
9    layouts::{Base2K, Degree, GLWEInfos, GLWESecretToBackendRef, GetDegree, LWEInfos, Rank},
10};
11
12/// DFT-domain (prepared) variant of [`GLWESecret`].
13///
14/// Stores the GLWE secret key with polynomials in the frequency domain
15/// for fast multiplication during encryption and decryption. Tied to a
16/// specific backend via `B: Backend`.
17pub struct GLWESecretPrepared<D: Data, B: Backend> {
18    pub(crate) data: SvpPPol<D, B>,
19    pub(crate) dist: Distribution,
20}
21
22pub type GLWESecretPreparedBackendRef<'a, B> = GLWESecretPrepared<<B as Backend>::BufRef<'a>, B>;
23pub type GLWESecretPreparedBackendMut<'a, B> = GLWESecretPrepared<<B as Backend>::BufMut<'a>, B>;
24
25impl<D: Data, BE: Backend> GetDistribution for GLWESecretPrepared<D, BE> {
26    fn dist(&self) -> &Distribution {
27        &self.dist
28    }
29}
30
31impl<D: Data, BE: Backend> GetDistributionMut for GLWESecretPrepared<D, BE> {
32    fn dist_mut(&mut self) -> &mut Distribution {
33        &mut self.dist
34    }
35}
36
37impl<D: Data, B: Backend> LWEInfos for GLWESecretPrepared<D, B> {
38    fn base2k(&self) -> Base2K {
39        Base2K(0)
40    }
41
42    fn n(&self) -> Degree {
43        Degree(self.data.n() as u32)
44    }
45
46    fn size(&self) -> usize {
47        self.data.size()
48    }
49}
50impl<D: Data, B: Backend> LWEInfos for &mut GLWESecretPrepared<D, B> {
51    fn base2k(&self) -> Base2K {
52        (**self).base2k()
53    }
54
55    fn n(&self) -> Degree {
56        (**self).n()
57    }
58
59    fn size(&self) -> usize {
60        (**self).size()
61    }
62}
63impl<D: Data, B: Backend> GLWEInfos for GLWESecretPrepared<D, B> {
64    fn rank(&self) -> Rank {
65        Rank(self.data.cols() as u32)
66    }
67}
68
69impl<D: Data, B: Backend> GLWEInfos for &mut GLWESecretPrepared<D, B> {
70    fn rank(&self) -> Rank {
71        (**self).rank()
72    }
73}
74
75pub trait GLWESecretPreparedFactory<B: Backend>
76where
77    Self: GetDegree + SvpPPolBytesOf + SvpPPolAlloc<B> + SvpPrepare<B>,
78{
79    fn glwe_secret_prepared_alloc(&self, rank: Rank) -> GLWESecretPrepared<B::OwnedBuf, B> {
80        GLWESecretPrepared {
81            data: self.svp_ppol_alloc(rank.into()),
82            dist: Distribution::NONE,
83        }
84    }
85    fn glwe_secret_prepared_alloc_from_infos<A>(&self, infos: &A) -> GLWESecretPrepared<B::OwnedBuf, B>
86    where
87        A: GLWEInfos,
88    {
89        assert_eq!(self.ring_degree(), infos.n());
90        self.glwe_secret_prepared_alloc(infos.rank())
91    }
92
93    fn glwe_secret_prepared_bytes_of(&self, rank: Rank) -> usize {
94        self.bytes_of_svp_ppol(rank.into())
95    }
96    fn glwe_secret_prepared_bytes_of_from_infos<A>(&self, infos: &A) -> usize
97    where
98        A: GLWEInfos,
99    {
100        assert_eq!(self.ring_degree(), infos.n());
101        self.glwe_secret_prepared_bytes_of(infos.rank())
102    }
103
104    fn glwe_secret_prepare<R, O>(&self, res: &mut R, other: &O)
105    where
106        R: GLWESecretPreparedToBackendMut<B> + GetDistributionMut,
107        O: GLWESecretToBackendRef<B> + GetDistribution,
108    {
109        {
110            let mut res = res.to_backend_mut();
111            let other = other.to_backend_ref();
112            for i in 0..res.rank().into() {
113                self.svp_prepare(&mut res.data, i, &other.data, i);
114            }
115        }
116
117        *res.dist_mut() = *other.dist();
118    }
119}
120
121impl<B: Backend> GLWESecretPreparedFactory<B> for Module<B> where
122    Self: GetDegree + SvpPPolBytesOf + SvpPPolAlloc<B> + SvpPrepare<B>
123{
124}
125
126// module-only API: allocation/size helpers are provided by `GLWESecretPreparedFactory` on `Module`.
127
128impl<D: Data, B: Backend> GLWESecretPrepared<D, B> {
129    pub fn n(&self) -> Degree {
130        Degree(self.data.n() as u32)
131    }
132
133    pub fn rank(&self) -> Rank {
134        Rank(self.data.cols() as u32)
135    }
136}
137
138// module-only API: preparation is provided by `GLWESecretPreparedFactory` on `Module`.
139
140pub trait GLWESecretPreparedToBackendRef<B: Backend> {
141    fn to_backend_ref(&self) -> GLWESecretPreparedBackendRef<'_, B>;
142}
143
144impl<B: Backend> GLWESecretPreparedToBackendRef<B> for GLWESecretPrepared<B::OwnedBuf, B> {
145    fn to_backend_ref(&self) -> GLWESecretPreparedBackendRef<'_, B> {
146        GLWESecretPrepared {
147            dist: self.dist,
148            data: self.data.to_backend_ref(),
149        }
150    }
151}
152
153pub trait GLWESecretPreparedToBackendMut<B: Backend> {
154    fn to_backend_mut(&mut self) -> GLWESecretPreparedBackendMut<'_, B>;
155}
156
157impl<B: Backend> GLWESecretPreparedToBackendMut<B> for GLWESecretPrepared<B::OwnedBuf, B> {
158    fn to_backend_mut(&mut self) -> GLWESecretPreparedBackendMut<'_, B> {
159        GLWESecretPrepared {
160            dist: self.dist,
161            data: self.data.to_backend_mut(),
162        }
163    }
164}