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, 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
 20impl<D: Data, B: Backend> LWEInfos for GLWEPublicKeyPrepared<D, B> {
 21    fn base2k(&self) -> Base2K {
 22        self.base2k
 23    }
 24
 25    fn k(&self) -> TorusPrecision {
 26        self.k
 27    }
 28
 29    fn size(&self) -> usize {
 30        self.data.size()
 31    }
 32
 33    fn n(&self) -> Degree {
 34        Degree(self.data.n() as u32)
 35    }
 36}
 37
 38impl<D: Data, B: Backend> GLWEInfos for GLWEPublicKeyPrepared<D, B> {
 39    fn rank(&self) -> Rank {
 40        Rank(self.data.cols() as u32 - 1)
 41    }
 42}
 43
 44pub struct GLWEPublicKeyPreparedBuilder<D: Data, B: Backend> {
 45    data: Option<VecZnxDft<D, B>>,
 46    base2k: Option<Base2K>,
 47    k: Option<TorusPrecision>,
 48}
 49
 50impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> {
 51    #[inline]
 52    pub fn builder() -> GLWEPublicKeyPreparedBuilder<D, B> {
 53        GLWEPublicKeyPreparedBuilder {
 54            data: None,
 55            base2k: None,
 56            k: None,
 57        }
 58    }
 59}
 60
 61impl<B: Backend> GLWEPublicKeyPreparedBuilder<Vec<u8>, B> {
 62    #[inline]
 63    pub fn layout<A>(mut self, layout: &A) -> Self
 64    where
 65        A: GLWEInfos,
 66        B: VecZnxDftAllocBytesImpl<B>,
 67    {
 68        self.data = Some(VecZnxDft::alloc(
 69            layout.n().into(),
 70            (layout.rank() + 1).into(),
 71            layout.size(),
 72        ));
 73        self.base2k = Some(layout.base2k());
 74        self.k = Some(layout.k());
 75        self
 76    }
 77}
 78
 79impl<D: Data, B: Backend> GLWEPublicKeyPreparedBuilder<D, B> {
 80    #[inline]
 81    pub fn data(mut self, data: VecZnxDft<D, B>) -> Self {
 82        self.data = Some(data);
 83        self
 84    }
 85    #[inline]
 86    pub fn base2k(mut self, base2k: Base2K) -> Self {
 87        self.base2k = Some(base2k);
 88        self
 89    }
 90    #[inline]
 91    pub fn k(mut self, k: TorusPrecision) -> Self {
 92        self.k = Some(k);
 93        self
 94    }
 95
 96    pub fn build(self) -> Result<GLWEPublicKeyPrepared<D, B>, BuildError> {
 97        let data: VecZnxDft<D, B> = self.data.ok_or(BuildError::MissingData)?;
 98        let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
 99        let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
100
101        if base2k == 0_u32 {
102            return Err(BuildError::ZeroBase2K);
103        }
104
105        if k == 0_u32 {
106            return Err(BuildError::ZeroTorusPrecision);
107        }
108
109        if data.n() == 0 {
110            return Err(BuildError::ZeroDegree);
111        }
112
113        if data.cols() == 0 {
114            return Err(BuildError::ZeroCols);
115        }
116
117        if data.size() == 0 {
118            return Err(BuildError::ZeroLimbs);
119        }
120
121        Ok(GLWEPublicKeyPrepared {
122            data,
123            base2k,
124            k,
125            dist: Distribution::NONE,
126        })
127    }
128}
129
130impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
131    pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
132    where
133        A: GLWEInfos,
134        Module<B>: VecZnxDftAlloc<B>,
135    {
136        debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
137        Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank())
138    }
139
140    pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
141    where
142        Module<B>: VecZnxDftAlloc<B>,
143    {
144        Self {
145            data: module.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
146            base2k,
147            k,
148            dist: Distribution::NONE,
149        }
150    }
151
152    pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
153    where
154        A: GLWEInfos,
155        Module<B>: VecZnxDftAllocBytes,
156    {
157        debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
158        Self::alloc_bytes_with(module, infos.base2k(), infos.k(), infos.rank())
159    }
160
161    pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
162    where
163        Module<B>: VecZnxDftAllocBytes,
164    {
165        module.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
166    }
167}
168
169impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEPublicKeyPrepared<Vec<u8>, B>> for GLWEPublicKey<D>
170where
171    Module<B>: VecZnxDftAlloc<B> + VecZnxDftApply<B>,
172{
173    fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEPublicKeyPrepared<Vec<u8>, B> {
174        let mut pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = GLWEPublicKeyPrepared::alloc(module, self);
175        pk_prepared.prepare(module, self, scratch);
176        pk_prepared
177    }
178}
179
180impl<B: Backend, A: GLWEInfos> PrepareScratchSpace<B, A> for GLWEPublicKeyPrepared<Vec<u8>, B> {
181    fn prepare_scratch_space(_module: &Module<B>, _infos: &A) -> usize {
182        0
183    }
184}
185
186impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEPublicKey<DR>> for GLWEPublicKeyPrepared<DM, B>
187where
188    Module<B>: VecZnxDftApply<B>,
189{
190    fn prepare(&mut self, module: &Module<B>, other: &GLWEPublicKey<DR>, _scratch: &mut Scratch<B>) {
191        #[cfg(debug_assertions)]
192        {
193            assert_eq!(self.n(), other.n());
194            assert_eq!(self.size(), other.size());
195        }
196
197        (0..(self.rank() + 1).into()).for_each(|i| {
198            module.vec_znx_dft_apply(1, 0, &mut self.data, i, &other.data, i);
199        });
200        self.k = other.k();
201        self.base2k = other.base2k();
202        self.dist = other.dist;
203    }
204}
205
206pub trait GLWEPublicKeyPreparedToMut<B: Backend> {
207    fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B>;
208}
209
210impl<D: DataMut, B: Backend> GLWEPublicKeyPreparedToMut<B> for GLWEPublicKeyPrepared<D, B> {
211    fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B> {
212        GLWEPublicKeyPrepared {
213            dist: self.dist,
214            k: self.k,
215            base2k: self.base2k,
216            data: self.data.to_mut(),
217        }
218    }
219}
220
221pub trait GLWEPublicKeyPreparedToRef<B: Backend> {
222    fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B>;
223}
224
225impl<D: DataRef, B: Backend> GLWEPublicKeyPreparedToRef<B> for GLWEPublicKeyPrepared<D, B> {
226    fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B> {
227        GLWEPublicKeyPrepared {
228            data: self.data.to_ref(),
229            dist: self.dist,
230            k: self.k,
231            base2k: self.base2k,
232        }
233    }
234}