arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/ggsw/layout.rs
core/src/ggsw/layout.rsRaw
  1use backend::hal::{
  2    api::{FillUniform, Reset, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo},
  4};
  5use std::fmt;
  6
  7use crate::{GLWECiphertext, Infos};
  8
  9pub trait GGSWLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>;
 10
 11#[derive(PartialEq, Eq, Clone)]
 12pub struct GGSWCiphertext<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 GGSWCiphertext<D> {
 20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 21        write!(
 22            f,
 23            "(GGSWCiphertext: basek={} k={} digits={}) {}",
 24            self.basek, self.k, self.digits, self.data
 25        )
 26    }
 27}
 28
 29impl<D: DataMut> Reset for GGSWCiphertext<D>
 30where
 31    MatZnx<D>: Reset,
 32{
 33    fn reset(&mut self) {
 34        self.data.reset();
 35        self.basek = 0;
 36        self.k = 0;
 37        self.digits = 0;
 38    }
 39}
 40
 41impl<D: DataMut> FillUniform for GGSWCiphertext<D>
 42where
 43    MatZnx<D>: FillUniform,
 44{
 45    fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
 46        self.data.fill_uniform(source);
 47    }
 48}
 49
 50impl<D: DataRef> GGSWCiphertext<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> GGSWCiphertext<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 GGSWCiphertext<Vec<u8>> {
 71    pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
 72        let size: usize = k.div_ceil(basek);
 73        debug_assert!(digits > 0, "invalid ggsw: `digits` == 0");
 74
 75        debug_assert!(
 76            size > digits,
 77            "invalid ggsw: ceil(k/basek): {} <= digits: {}",
 78            size,
 79            digits
 80        );
 81
 82        assert!(
 83            rows * digits <= size,
 84            "invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
 85            rows,
 86            digits,
 87            size
 88        );
 89
 90        Self {
 91            data: MatZnx::alloc(n, rows, rank + 1, rank + 1, k.div_ceil(basek)),
 92            basek,
 93            k: k,
 94            digits,
 95        }
 96    }
 97
 98    pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
 99        let size: usize = k.div_ceil(basek);
100        debug_assert!(
101            size > digits,
102            "invalid ggsw: ceil(k/basek): {} <= digits: {}",
103            size,
104            digits
105        );
106
107        assert!(
108            rows * digits <= size,
109            "invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
110            rows,
111            digits,
112            size
113        );
114
115        MatZnx::alloc_bytes(n, rows, rank + 1, rank + 1, size)
116    }
117}
118
119impl<D: Data> Infos for GGSWCiphertext<D> {
120    type Inner = MatZnx<D>;
121
122    fn inner(&self) -> &Self::Inner {
123        &self.data
124    }
125
126    fn basek(&self) -> usize {
127        self.basek
128    }
129
130    fn k(&self) -> usize {
131        self.k
132    }
133}
134
135impl<D: Data> GGSWCiphertext<D> {
136    pub fn rank(&self) -> usize {
137        self.data.cols_out() - 1
138    }
139
140    pub fn digits(&self) -> usize {
141        self.digits
142    }
143}
144
145use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
146
147impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> {
148    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
149        self.k = reader.read_u64::<LittleEndian>()? as usize;
150        self.basek = reader.read_u64::<LittleEndian>()? as usize;
151        self.digits = reader.read_u64::<LittleEndian>()? as usize;
152        self.data.read_from(reader)
153    }
154}
155
156impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
157    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
158        writer.write_u64::<LittleEndian>(self.k as u64)?;
159        writer.write_u64::<LittleEndian>(self.basek as u64)?;
160        writer.write_u64::<LittleEndian>(self.digits as u64)?;
161        self.data.write_to(writer)
162    }
163}