arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/ggsw_ct.rs
poulpy-core/src/layouts/ggsw_ct.rsRaw
  1use poulpy_hal::{
  2    layouts::{
  3        Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos,
  4    },
  5    source::Source,
  6};
  7use std::fmt;
  8
  9use crate::layouts::{Base2K, Degree, Dnum, Dsize, GLWE, GLWEInfos, GetDegree, LWEInfos, Rank, TorusPrecision};
 10
 11pub trait GGSWInfos
 12where
 13    Self: GLWEInfos,
 14{
 15    fn dnum(&self) -> Dnum;
 16    fn dsize(&self) -> Dsize;
 17    fn ggsw_layout(&self) -> GGSWLayout {
 18        GGSWLayout {
 19            n: self.n(),
 20            base2k: self.base2k(),
 21            k: self.k(),
 22            rank: self.rank(),
 23            dnum: self.dnum(),
 24            dsize: self.dsize(),
 25        }
 26    }
 27}
 28
 29#[derive(PartialEq, Eq, Copy, Clone, Debug)]
 30pub struct GGSWLayout {
 31    pub n: Degree,
 32    pub base2k: Base2K,
 33    pub k: TorusPrecision,
 34    pub rank: Rank,
 35    pub dnum: Dnum,
 36    pub dsize: Dsize,
 37}
 38
 39impl LWEInfos for GGSWLayout {
 40    fn base2k(&self) -> Base2K {
 41        self.base2k
 42    }
 43
 44    fn k(&self) -> TorusPrecision {
 45        self.k
 46    }
 47
 48    fn n(&self) -> Degree {
 49        self.n
 50    }
 51}
 52impl GLWEInfos for GGSWLayout {
 53    fn rank(&self) -> Rank {
 54        self.rank
 55    }
 56}
 57
 58impl GGSWInfos for GGSWLayout {
 59    fn dsize(&self) -> Dsize {
 60        self.dsize
 61    }
 62
 63    fn dnum(&self) -> Dnum {
 64        self.dnum
 65    }
 66}
 67
 68#[derive(PartialEq, Eq, Clone)]
 69pub struct GGSW<D: Data> {
 70    pub(crate) data: MatZnx<D>,
 71    pub(crate) k: TorusPrecision,
 72    pub(crate) base2k: Base2K,
 73    pub(crate) dsize: Dsize,
 74}
 75
 76impl<D: Data> LWEInfos for GGSW<D> {
 77    fn n(&self) -> Degree {
 78        Degree(self.data.n() as u32)
 79    }
 80
 81    fn base2k(&self) -> Base2K {
 82        self.base2k
 83    }
 84
 85    fn k(&self) -> TorusPrecision {
 86        self.k
 87    }
 88
 89    fn size(&self) -> usize {
 90        self.data.size()
 91    }
 92}
 93
 94impl<D: Data> GLWEInfos for GGSW<D> {
 95    fn rank(&self) -> Rank {
 96        Rank(self.data.cols_out() as u32 - 1)
 97    }
 98}
 99
100impl<D: Data> GGSWInfos for GGSW<D> {
101    fn dsize(&self) -> Dsize {
102        self.dsize
103    }
104
105    fn dnum(&self) -> Dnum {
106        Dnum(self.data.rows() as u32)
107    }
108}
109
110impl<D: DataRef> fmt::Debug for GGSW<D> {
111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112        write!(f, "{}", self.data)
113    }
114}
115
116impl<D: DataRef> fmt::Display for GGSW<D> {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(
119            f,
120            "(GGSW: k: {} base2k: {} dsize: {}) {}",
121            self.k().0,
122            self.base2k().0,
123            self.dsize().0,
124            self.data
125        )
126    }
127}
128
129impl<D: DataMut> FillUniform for GGSW<D> {
130    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
131        self.data.fill_uniform(log_bound, source);
132    }
133}
134
135impl<D: DataRef> GGSW<D> {
136    pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
137        GLWE {
138            k: self.k,
139            base2k: self.base2k,
140            data: self.data.at(row, col),
141        }
142    }
143}
144
145impl<D: DataMut> GGSW<D> {
146    pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
147        GLWE {
148            k: self.k,
149            base2k: self.base2k,
150            data: self.data.at_mut(row, col),
151        }
152    }
153}
154
155impl<B: Backend> GGSWAlloc for Module<B> where Self: GetDegree {}
156
157pub trait GGSWAlloc
158where
159    Self: GetDegree,
160{
161    fn alloc_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<Vec<u8>> {
162        let size: usize = k.0.div_ceil(base2k.0) as usize;
163        debug_assert!(
164            size as u32 > dsize.0,
165            "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
166            dsize.0
167        );
168
169        assert!(
170            dnum.0 * dsize.0 <= size as u32,
171            "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
172            dnum.0,
173            dsize.0,
174        );
175
176        GGSW {
177            data: MatZnx::alloc(
178                self.n().into(),
179                dnum.into(),
180                (rank + 1).into(),
181                (rank + 1).into(),
182                k.0.div_ceil(base2k.0) as usize,
183            ),
184            k,
185            base2k,
186            dsize,
187        }
188    }
189
190    fn alloc_ggsw_from_infos<A>(&self, infos: &A) -> GGSW<Vec<u8>>
191    where
192        A: GGSWInfos,
193    {
194        self.alloc_ggsw(
195            infos.base2k(),
196            infos.k(),
197            infos.rank(),
198            infos.dnum(),
199            infos.dsize(),
200        )
201    }
202
203    fn bytes_of_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
204        let size: usize = k.0.div_ceil(base2k.0) as usize;
205        debug_assert!(
206            size as u32 > dsize.0,
207            "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
208            dsize.0
209        );
210
211        assert!(
212            dnum.0 * dsize.0 <= size as u32,
213            "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
214            dnum.0,
215            dsize.0,
216        );
217
218        MatZnx::bytes_of(
219            self.n().into(),
220            dnum.into(),
221            (rank + 1).into(),
222            (rank + 1).into(),
223            k.0.div_ceil(base2k.0) as usize,
224        )
225    }
226
227    fn bytes_of_ggsw_from_infos<A>(&self, infos: &A) -> usize
228    where
229        A: GGSWInfos,
230    {
231        self.bytes_of_ggsw(
232            infos.base2k(),
233            infos.k(),
234            infos.rank(),
235            infos.dnum(),
236            infos.dsize(),
237        )
238    }
239}
240
241impl GGSW<Vec<u8>> {
242    pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
243    where
244        A: GGSWInfos,
245        M: GGSWAlloc,
246    {
247        module.alloc_ggsw_from_infos(infos)
248    }
249
250    pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
251    where
252        M: GGSWAlloc,
253    {
254        module.alloc_ggsw(base2k, k, rank, dnum, dsize)
255    }
256
257    pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
258    where
259        A: GGSWInfos,
260        M: GGSWAlloc,
261    {
262        module.bytes_of_ggsw_from_infos(infos)
263    }
264
265    pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
266    where
267        M: GGSWAlloc,
268    {
269        module.bytes_of_ggsw(base2k, k, rank, dnum, dsize)
270    }
271}
272
273use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
274
275impl<D: DataMut> ReaderFrom for GGSW<D> {
276    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
277        self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
278        self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
279        self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
280        self.data.read_from(reader)
281    }
282}
283
284impl<D: DataRef> WriterTo for GGSW<D> {
285    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
286        writer.write_u32::<LittleEndian>(self.k.into())?;
287        writer.write_u32::<LittleEndian>(self.base2k.into())?;
288        writer.write_u32::<LittleEndian>(self.dsize.into())?;
289        self.data.write_to(writer)
290    }
291}
292
293pub trait GGSWToMut {
294    fn to_mut(&mut self) -> GGSW<&mut [u8]>;
295}
296
297impl<D: DataMut> GGSWToMut for GGSW<D> {
298    fn to_mut(&mut self) -> GGSW<&mut [u8]> {
299        GGSW {
300            dsize: self.dsize,
301            k: self.k,
302            base2k: self.base2k,
303            data: self.data.to_mut(),
304        }
305    }
306}
307
308pub trait GGSWToRef {
309    fn to_ref(&self) -> GGSW<&[u8]>;
310}
311
312impl<D: DataRef> GGSWToRef for GGSW<D> {
313    fn to_ref(&self) -> GGSW<&[u8]> {
314        GGSW {
315            dsize: self.dsize,
316            k: self.k,
317            base2k: self.base2k,
318            data: self.data.to_ref(),
319        }
320    }
321}