arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/gglwe_ct.rs
poulpy-core/src/layouts/gglwe_ct.rsRaw
  1use poulpy_hal::{
  2    layouts::{Data, DataMut, DataRef, FillUniform, MatZnx, ReaderFrom, Reset, WriterTo},
  3    source::Source,
  4};
  5
  6use crate::layouts::{GLWECiphertext, Infos};
  7use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
  8
  9use std::fmt;
 10
 11#[derive(PartialEq, Eq, Clone)]
 12pub struct GGLWECiphertext<D: Data> {
 13    pub(crate) data: MatZnx<D>,
 14    pub(crate) basek: usize,
 15    pub(crate) k: usize,
 16    pub(crate) digits: usize,
 17}
 18
 19impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> {
 20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 21        write!(f, "{}", self)
 22    }
 23}
 24
 25impl<D: DataMut> FillUniform for GGLWECiphertext<D> {
 26    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
 27        self.data.fill_uniform(log_bound, source);
 28    }
 29}
 30
 31impl<D: DataMut> Reset for GGLWECiphertext<D> {
 32    fn reset(&mut self) {
 33        self.data.reset();
 34        self.basek = 0;
 35        self.k = 0;
 36        self.digits = 0;
 37    }
 38}
 39
 40impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
 41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 42        write!(
 43            f,
 44            "(GGLWECiphertext: basek={} k={} digits={}) {}",
 45            self.basek, self.k, self.digits, self.data
 46        )
 47    }
 48}
 49
 50impl<D: DataRef> GGLWECiphertext<D> {
 51    pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
 52        GLWECiphertext {
 53            data: self.data.at(row, col),
 54            basek: self.basek,
 55            k: self.k,
 56        }
 57    }
 58}
 59
 60impl<D: DataMut> GGLWECiphertext<D> {
 61    pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
 62        GLWECiphertext {
 63            data: self.data.at_mut(row, col),
 64            basek: self.basek,
 65            k: self.k,
 66        }
 67    }
 68}
 69
 70impl GGLWECiphertext<Vec<u8>> {
 71    pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
 72        let size: usize = k.div_ceil(basek);
 73        debug_assert!(
 74            size > digits,
 75            "invalid gglwe: ceil(k/basek): {} <= digits: {}",
 76            size,
 77            digits
 78        );
 79
 80        assert!(
 81            rows * digits <= size,
 82            "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
 83            rows,
 84            digits,
 85            size
 86        );
 87
 88        Self {
 89            data: MatZnx::alloc(n, rows, rank_in, rank_out + 1, size),
 90            basek,
 91            k,
 92            digits,
 93        }
 94    }
 95
 96    pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize {
 97        let size: usize = k.div_ceil(basek);
 98        debug_assert!(
 99            size > digits,
100            "invalid gglwe: ceil(k/basek): {} <= digits: {}",
101            size,
102            digits
103        );
104
105        assert!(
106            rows * digits <= size,
107            "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
108            rows,
109            digits,
110            size
111        );
112
113        MatZnx::alloc_bytes(n, rows, rank_in, rank_out + 1, rows)
114    }
115}
116
117impl<D: Data> Infos for GGLWECiphertext<D> {
118    type Inner = MatZnx<D>;
119
120    fn inner(&self) -> &Self::Inner {
121        &self.data
122    }
123
124    fn basek(&self) -> usize {
125        self.basek
126    }
127
128    fn k(&self) -> usize {
129        self.k
130    }
131}
132
133impl<D: Data> GGLWECiphertext<D> {
134    pub fn rank(&self) -> usize {
135        self.data.cols_out() - 1
136    }
137
138    pub fn digits(&self) -> usize {
139        self.digits
140    }
141
142    pub fn rank_in(&self) -> usize {
143        self.data.cols_in()
144    }
145
146    pub fn rank_out(&self) -> usize {
147        self.data.cols_out() - 1
148    }
149}
150
151impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> {
152    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
153        self.k = reader.read_u64::<LittleEndian>()? as usize;
154        self.basek = reader.read_u64::<LittleEndian>()? as usize;
155        self.digits = reader.read_u64::<LittleEndian>()? as usize;
156        self.data.read_from(reader)
157    }
158}
159
160impl<D: DataRef> WriterTo for GGLWECiphertext<D> {
161    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
162        writer.write_u64::<LittleEndian>(self.k as u64)?;
163        writer.write_u64::<LittleEndian>(self.basek as u64)?;
164        writer.write_u64::<LittleEndian>(self.digits as u64)?;
165        self.data.write_to(writer)
166    }
167}