arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/prepared/glwe_pk.rs
poulpy-core/src/layouts/prepared/glwe_pk.rsRaw
  1use poulpy_hal::{
  2    api::{VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, ZnxInfos},
  4    oep::VecZnxDftAllocBytesImpl,
  5};
  6
  7use crate::{
  8    dist::Distribution,
  9    layouts::{Base2K, BuildError, Degree, GLWEInfos, GLWEPublicKey, GLWEPublicKeyToRef, LWEInfos, Rank, TorusPrecision},
 10};
 11
 12#[derive(PartialEq, Eq)]
 13pub struct GLWEPublicKeyPrepared<D: Data, B: Backend> {
 14    pub(crate) data: VecZnxDft<D, B>,
 15    pub(crate) base2k: Base2K,
 16    pub(crate) k: TorusPrecision,
 17    pub(crate) dist: Distribution,
 18}
 19
 20pub(crate) trait SetDist {
 21    fn set_dist(&mut self, dist: Distribution);
 22}
 23
 24impl<D: Data, B: Backend> SetDist for GLWEPublicKeyPrepared<D, B> {
 25    fn set_dist(&mut self, dist: Distribution) {
 26        self.dist = dist
 27    }
 28}
 29
 30impl<D: Data, B: Backend> LWEInfos for GLWEPublicKeyPrepared<D, B> {
 31    fn base2k(&self) -> Base2K {
 32        self.base2k
 33    }
 34
 35    fn k(&self) -> TorusPrecision {
 36        self.k
 37    }
 38
 39    fn size(&self) -> usize {
 40        self.data.size()
 41    }
 42
 43    fn n(&self) -> Degree {
 44        Degree(self.data.n() as u32)
 45    }
 46}
 47
 48impl<D: Data, B: Backend> GLWEInfos for GLWEPublicKeyPrepared<D, B> {
 49    fn rank(&self) -> Rank {
 50        Rank(self.data.cols() as u32 - 1)
 51    }
 52}
 53
 54pub struct GLWEPublicKeyPreparedBuilder<D: Data, B: Backend> {
 55    data: Option<VecZnxDft<D, B>>,
 56    base2k: Option<Base2K>,
 57    k: Option<TorusPrecision>,
 58}
 59
 60impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> {
 61    #[inline]
 62    pub fn builder() -> GLWEPublicKeyPreparedBuilder<D, B> {
 63        GLWEPublicKeyPreparedBuilder {
 64            data: None,
 65            base2k: None,
 66            k: None,
 67        }
 68    }
 69}
 70
 71impl<B: Backend> GLWEPublicKeyPreparedBuilder<Vec<u8>, B> {
 72    #[inline]
 73    pub fn layout<A>(mut self, layout: &A) -> Self
 74    where
 75        A: GLWEInfos,
 76        B: VecZnxDftAllocBytesImpl<B>,
 77    {
 78        self.data = Some(VecZnxDft::alloc(
 79            layout.n().into(),
 80            (layout.rank() + 1).into(),
 81            layout.size(),
 82        ));
 83        self.base2k = Some(layout.base2k());
 84        self.k = Some(layout.k());
 85        self
 86    }
 87}
 88
 89impl<D: Data, B: Backend> GLWEPublicKeyPreparedBuilder<D, B> {
 90    #[inline]
 91    pub fn data(mut self, data: VecZnxDft<D, B>) -> Self {
 92        self.data = Some(data);
 93        self
 94    }
 95    #[inline]
 96    pub fn base2k(mut self, base2k: Base2K) -> Self {
 97        self.base2k = Some(base2k);
 98        self
 99    }
100    #[inline]
101    pub fn k(mut self, k: TorusPrecision) -> Self {
102        self.k = Some(k);
103        self
104    }
105
106    pub fn build(self) -> Result<GLWEPublicKeyPrepared<D, B>, BuildError> {
107        let data: VecZnxDft<D, B> = self.data.ok_or(BuildError::MissingData)?;
108        let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
109        let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
110
111        if base2k == 0_u32 {
112            return Err(BuildError::ZeroBase2K);
113        }
114
115        if k == 0_u32 {
116            return Err(BuildError::ZeroTorusPrecision);
117        }
118
119        if data.n() == 0 {
120            return Err(BuildError::ZeroDegree);
121        }
122
123        if data.cols() == 0 {
124            return Err(BuildError::ZeroCols);
125        }
126
127        if data.size() == 0 {
128            return Err(BuildError::ZeroLimbs);
129        }
130
131        Ok(GLWEPublicKeyPrepared {
132            data,
133            base2k,
134            k,
135            dist: Distribution::NONE,
136        })
137    }
138}
139
140impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
141    pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
142    where
143        A: GLWEInfos,
144        Module<B>: VecZnxDftAlloc<B>,
145    {
146        debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
147        Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank())
148    }
149
150    pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
151    where
152        Module<B>: VecZnxDftAlloc<B>,
153    {
154        Self {
155            data: module.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
156            base2k,
157            k,
158            dist: Distribution::NONE,
159        }
160    }
161
162    pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
163    where
164        A: GLWEInfos,
165        Module<B>: VecZnxDftAllocBytes,
166    {
167        debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
168        Self::alloc_bytes_with(module, infos.base2k(), infos.k(), infos.rank())
169    }
170
171    pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
172    where
173        Module<B>: VecZnxDftAllocBytes,
174    {
175        module.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
176    }
177}
178
179pub trait GLWEPublicKeyPrepareTmpBytes {
180    fn glwe_public_key_prepare_tmp_bytes<A>(&self, infos: &A)
181    where
182        A: GLWEInfos;
183}
184
185impl<B: Backend> GLWEPublicKeyPrepareTmpBytes for Module<B> {
186    fn glwe_public_key_prepare_tmp_bytes<A>(&self, infos: &A)
187    where
188        A: GLWEInfos,
189    {
190        0
191    }
192}
193
194impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
195    pub fn prepare_tmp_bytes<A>(&self, module: &Module<B>, infos: &A)
196    where
197        A: GLWEInfos,
198        Module<B>: GLWEPublicKeyPrepareTmpBytes,
199    {
200        module.glwe_public_key_prepare_tmp_bytes(infos);
201    }
202}
203
204pub trait GLWEPublicKeyPrepare<B: Backend> {
205    fn glwe_public_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
206    where
207        R: GLWEPublicKeyPreparedToMut<B> + SetDist,
208        O: GLWEPublicKeyToRef;
209}
210
211impl<B: Backend> GLWEPublicKeyPrepare<B> for Module<B>
212where
213    Module<B>: VecZnxDftAlloc<B> + VecZnxDftApply<B>,
214{
215    fn glwe_public_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
216    where
217        R: GLWEPublicKeyPreparedToMut<B> + SetDist,
218        O: GLWEPublicKeyToRef,
219    {
220        {
221            let res: GLWEPublicKeyPrepared<&mut [u8], B> = res.to_mut();
222            let other: GLWEPublicKey<&[u8]> = other.to_ref();
223
224            assert_eq!(res.n(), self.n() as u32);
225            assert_eq!(other.n(), self.n() as u32);
226            assert_eq!(res.size(), other.size());
227            assert_eq!(res.k(), other.k());
228            assert_eq!(res.base2k(), other.base2k());
229
230            for i in 0..(self.rank() + 1).into() {
231                self.vec_znx_dft_apply(1, 0, &mut self.data, i, &other.data, i);
232            }
233        }
234
235        res.set_dist(other.dist);
236    }
237}
238
239impl<D: DataMut, B: Backend> GLWEPublicKeyPrepared<D, B>
240where
241    Module<B>: GLWEPublicKeyPrepare<B>,
242{
243    pub fn prepare<O>(&mut self, module: &Module<B>, other: &O, scratch: &mut Scratch<B>)
244    where
245        O: GLWEPublicKeyToRef,
246    {
247        module.glwe_public_key_prepare(self, other, scratch);
248    }
249}
250
251pub trait GLWEPublicKeyPrepareAlloc<B: Backend> {
252    fn glwe_public_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
253    where
254        O: GLWEPublicKeyToRef;
255}
256
257impl<B: Backend> GLWEPublicKeyPrepareAlloc<B> for Module<B>
258where
259    Module<B>: GLWEPublicKeyPrepare<B>,
260{
261    fn glwe_public_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
262    where
263        O: GLWEPublicKeyToRef,
264    {
265        let mut ct_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = GLWEPublicKeyPrepared::alloc(self, other);
266        self.glwe_public_key_prepare(&mut ct_prepared, ct_prepared, scratch);
267        ct_prepared
268    }
269}
270
271impl<D: DataRef> GLWEPublicKey<D> {
272    pub fn prepare_alloc<B: Backend>(&self, module: &Module<B>, scratch: &mut Scratch<B>)
273    where
274        Module<B>: GLWEPublicKeyPrepareAlloc<B>,
275    {
276        module.glwe_public_key_prepare_alloc(self, scratch);
277    }
278}
279
280pub trait GLWEPublicKeyPreparedToMut<B: Backend> {
281    fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B>;
282}
283
284impl<D: DataMut, B: Backend> GLWEPublicKeyPreparedToMut<B> for GLWEPublicKeyPrepared<D, B> {
285    fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B> {
286        GLWEPublicKeyPrepared {
287            dist: self.dist,
288            k: self.k,
289            base2k: self.base2k,
290            data: self.data.to_mut(),
291        }
292    }
293}
294
295pub trait GLWEPublicKeyPreparedToRef<B: Backend> {
296    fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B>;
297}
298
299impl<D: DataRef, B: Backend> GLWEPublicKeyPreparedToRef<B> for GLWEPublicKeyPrepared<D, B> {
300    fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B> {
301        GLWEPublicKeyPrepared {
302            data: self.data.to_ref(),
303            dist: self.dist,
304            k: self.k,
305            base2k: self.base2k,
306        }
307    }
308}