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