arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/layout.rs
core/src/glwe/layout.rsRaw
  1use backend::hal::{
  2    api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform, ZnxInfos},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo},
  4};
  5use sampling::source::Source;
  6
  7use crate::{Decompress, GLWEOps, Infos, SetMetaData};
  8use std::fmt;
  9
 10#[derive(PartialEq, Eq, Clone)]
 11pub struct GLWECiphertext<D: Data> {
 12    pub data: VecZnx<D>,
 13    pub basek: usize,
 14    pub k: usize,
 15}
 16
 17impl<D: DataRef> fmt::Debug for GLWECiphertext<D> {
 18    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 19        write!(f, "{}", self)
 20    }
 21}
 22
 23impl<D: DataRef> fmt::Display for GLWECiphertext<D> {
 24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 25        write!(
 26            f,
 27            "GLWECiphertext: basek={} k={}: {}",
 28            self.basek(),
 29            self.k(),
 30            self.data
 31        )
 32    }
 33}
 34
 35impl<D: DataMut> Reset for GLWECiphertext<D>
 36where
 37    VecZnx<D>: Reset,
 38{
 39    fn reset(&mut self) {
 40        self.data.reset();
 41        self.basek = 0;
 42        self.k = 0;
 43    }
 44}
 45
 46impl<D: DataMut> FillUniform for GLWECiphertext<D>
 47where
 48    VecZnx<D>: FillUniform,
 49{
 50    fn fill_uniform(&mut self, source: &mut Source) {
 51        self.data.fill_uniform(source);
 52    }
 53}
 54
 55impl GLWECiphertext<Vec<u8>> {
 56    pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self {
 57        Self {
 58            data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)),
 59            basek,
 60            k,
 61        }
 62    }
 63
 64    pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize {
 65        VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek))
 66    }
 67}
 68
 69impl<D: Data> Infos for GLWECiphertext<D> {
 70    type Inner = VecZnx<D>;
 71
 72    fn inner(&self) -> &Self::Inner {
 73        &self.data
 74    }
 75
 76    fn basek(&self) -> usize {
 77        self.basek
 78    }
 79
 80    fn k(&self) -> usize {
 81        self.k
 82    }
 83}
 84
 85impl<D: Data> GLWECiphertext<D> {
 86    pub fn rank(&self) -> usize {
 87        self.cols() - 1
 88    }
 89}
 90
 91impl<D: DataRef> GLWECiphertext<D> {
 92    pub fn clone(&self) -> GLWECiphertext<Vec<u8>> {
 93        GLWECiphertext {
 94            data: self.data.clone(),
 95            basek: self.basek(),
 96            k: self.k(),
 97        }
 98    }
 99}
100
101impl<D: DataMut> SetMetaData for GLWECiphertext<D> {
102    fn set_k(&mut self, k: usize) {
103        self.k = k
104    }
105
106    fn set_basek(&mut self, basek: usize) {
107        self.basek = basek
108    }
109}
110
111pub trait GLWECiphertextToRef: Infos {
112    fn to_ref(&self) -> GLWECiphertext<&[u8]>;
113}
114
115impl<D: DataRef> GLWECiphertextToRef for GLWECiphertext<D> {
116    fn to_ref(&self) -> GLWECiphertext<&[u8]> {
117        GLWECiphertext {
118            data: self.data.to_ref(),
119            basek: self.basek,
120            k: self.k,
121        }
122    }
123}
124
125pub trait GLWECiphertextToMut: Infos {
126    fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>;
127}
128
129impl<D: DataMut> GLWECiphertextToMut for GLWECiphertext<D> {
130    fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> {
131        GLWECiphertext {
132            data: self.data.to_mut(),
133            basek: self.basek,
134            k: self.k,
135        }
136    }
137}
138
139impl<D: DataMut> GLWEOps for GLWECiphertext<D> where GLWECiphertext<D>: GLWECiphertextToMut + Infos + SetMetaData {}
140
141use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
142
143impl<D: DataMut> ReaderFrom for GLWECiphertext<D> {
144    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
145        self.k = reader.read_u64::<LittleEndian>()? as usize;
146        self.basek = reader.read_u64::<LittleEndian>()? as usize;
147        self.data.read_from(reader)
148    }
149}
150
151impl<D: DataRef> WriterTo for GLWECiphertext<D> {
152    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
153        writer.write_u64::<LittleEndian>(self.k as u64)?;
154        writer.write_u64::<LittleEndian>(self.basek as u64)?;
155        self.data.write_to(writer)
156    }
157}
158
159#[derive(PartialEq, Eq, Clone)]
160pub struct GLWECiphertextCompressed<D: Data> {
161    pub(crate) data: VecZnx<D>,
162    pub(crate) basek: usize,
163    pub(crate) k: usize,
164    pub(crate) rank: usize,
165    pub(crate) seed: [u8; 32],
166}
167
168impl<D: DataRef> fmt::Debug for GLWECiphertextCompressed<D> {
169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
170        write!(f, "{}", self)
171    }
172}
173
174impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        write!(
177            f,
178            "GLWECiphertextCompressed: basek={} k={} rank={} seed={:?}: {}",
179            self.basek(),
180            self.k(),
181            self.rank,
182            self.seed,
183            self.data
184        )
185    }
186}
187
188impl<D: DataMut> Reset for GLWECiphertextCompressed<D>
189where
190    VecZnx<D>: Reset,
191{
192    fn reset(&mut self) {
193        self.data.reset();
194        self.basek = 0;
195        self.k = 0;
196        self.rank = 0;
197        self.seed = [0u8; 32];
198    }
199}
200
201impl<D: DataMut> FillUniform for GLWECiphertextCompressed<D>
202where
203    VecZnx<D>: FillUniform,
204{
205    fn fill_uniform(&mut self, source: &mut Source) {
206        self.data.fill_uniform(source);
207    }
208}
209
210impl<D: Data> Infos for GLWECiphertextCompressed<D> {
211    type Inner = VecZnx<D>;
212
213    fn inner(&self) -> &Self::Inner {
214        &self.data
215    }
216
217    fn basek(&self) -> usize {
218        self.basek
219    }
220
221    fn k(&self) -> usize {
222        self.k
223    }
224}
225
226impl<D: Data> GLWECiphertextCompressed<D> {
227    pub fn rank(&self) -> usize {
228        self.rank
229    }
230}
231
232impl GLWECiphertextCompressed<Vec<u8>> {
233    pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self {
234        Self {
235            data: VecZnx::alloc(n, 1, k.div_ceil(basek)),
236            basek,
237            k,
238            rank,
239            seed: [0u8; 32],
240        }
241    }
242
243    pub fn bytes_of(n: usize, basek: usize, k: usize) -> usize {
244        GLWECiphertext::bytes_of(n, basek, k, 1)
245    }
246}
247
248impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> {
249    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
250        self.k = reader.read_u64::<LittleEndian>()? as usize;
251        self.basek = reader.read_u64::<LittleEndian>()? as usize;
252        self.rank = reader.read_u64::<LittleEndian>()? as usize;
253        reader.read(&mut self.seed)?;
254        self.data.read_from(reader)
255    }
256}
257
258impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> {
259    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
260        writer.write_u64::<LittleEndian>(self.k as u64)?;
261        writer.write_u64::<LittleEndian>(self.basek as u64)?;
262        writer.write_u64::<LittleEndian>(self.rank as u64)?;
263        writer.write_all(&self.seed)?;
264        self.data.write_to(writer)
265    }
266}
267
268impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GLWECiphertextCompressed<DR>> for GLWECiphertext<D> {
269    fn decompress(&mut self, module: &Module<B>, other: &GLWECiphertextCompressed<DR>)
270    where
271        Module<B>: VecZnxFillUniform + VecZnxCopy,
272    {
273        #[cfg(debug_assertions)]
274        {
275            assert_eq!(
276                self.n(),
277                other.data.n(),
278                "invalid receiver: self.n()={} != other.n()={}",
279                self.n(),
280                other.data.n()
281            );
282            assert_eq!(
283                self.size(),
284                other.size(),
285                "invalid receiver: self.size()={} != other.size()={}",
286                self.size(),
287                other.size()
288            );
289            assert_eq!(
290                self.rank(),
291                other.rank(),
292                "invalid receiver: self.rank()={} != other.rank()={}",
293                self.rank(),
294                other.rank()
295            );
296            let mut source: Source = Source::new(other.seed);
297            self.decompress_internal(module, other, &mut source);
298        }
299    }
300}
301
302impl<D: DataMut> GLWECiphertext<D> {
303    pub(crate) fn decompress_internal<DataOther, B: Backend>(
304        &mut self,
305        module: &Module<B>,
306        other: &GLWECiphertextCompressed<DataOther>,
307        source: &mut Source,
308    ) where
309        DataOther: DataRef,
310        Module<B>: VecZnxFillUniform + VecZnxCopy,
311    {
312        #[cfg(debug_assertions)]
313        {
314            assert_eq!(self.rank(), other.rank())
315        }
316
317        let k: usize = other.k;
318        let basek: usize = other.basek;
319        let cols: usize = other.rank() + 1;
320        module.vec_znx_copy(&mut self.data, 0, &other.data, 0);
321        (1..cols).for_each(|i| {
322            module.vec_znx_fill_uniform(basek, &mut self.data, i, k, source);
323        });
324
325        self.basek = basek;
326        self.k = k;
327    }
328}