arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/ggsw/layout.rs
core/src/ggsw/layout.rsRaw
  1use backend::hal::{
  2    api::{MatZnxAlloc, MatZnxAllocBytes, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
  4};
  5
  6use crate::{GLWECiphertext, Infos};
  7
  8pub trait GGSWLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>;
  9
 10#[derive(PartialEq, Eq)]
 11pub struct GGSWCiphertext<D: Data> {
 12    pub(crate) data: MatZnx<D>,
 13    pub(crate) basek: usize,
 14    pub(crate) k: usize,
 15    pub(crate) digits: usize,
 16}
 17
 18impl<D: DataRef> GGSWCiphertext<D> {
 19    pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
 20        GLWECiphertext {
 21            data: self.data.at(row, col),
 22            basek: self.basek,
 23            k: self.k,
 24        }
 25    }
 26}
 27
 28impl<D: DataMut> GGSWCiphertext<D> {
 29    pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
 30        GLWECiphertext {
 31            data: self.data.at_mut(row, col),
 32            basek: self.basek,
 33            k: self.k,
 34        }
 35    }
 36}
 37
 38impl GGSWCiphertext<Vec<u8>> {
 39    pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
 40    where
 41        Module<B>: MatZnxAlloc,
 42    {
 43        let size: usize = k.div_ceil(basek);
 44        debug_assert!(digits > 0, "invalid ggsw: `digits` == 0");
 45
 46        debug_assert!(
 47            size > digits,
 48            "invalid ggsw: ceil(k/basek): {} <= digits: {}",
 49            size,
 50            digits
 51        );
 52
 53        assert!(
 54            rows * digits <= size,
 55            "invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
 56            rows,
 57            digits,
 58            size
 59        );
 60
 61        Self {
 62            data: module.mat_znx_alloc(rows, rank + 1, rank + 1, k.div_ceil(basek)),
 63            basek,
 64            k: k,
 65            digits,
 66        }
 67    }
 68
 69    pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
 70    where
 71        Module<B>: MatZnxAllocBytes,
 72    {
 73        let size: usize = k.div_ceil(basek);
 74        debug_assert!(
 75            size > digits,
 76            "invalid ggsw: ceil(k/basek): {} <= digits: {}",
 77            size,
 78            digits
 79        );
 80
 81        assert!(
 82            rows * digits <= size,
 83            "invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
 84            rows,
 85            digits,
 86            size
 87        );
 88
 89        module.mat_znx_alloc_bytes(rows, rank + 1, rank + 1, size)
 90    }
 91}
 92
 93impl<D: Data> Infos for GGSWCiphertext<D> {
 94    type Inner = MatZnx<D>;
 95
 96    fn inner(&self) -> &Self::Inner {
 97        &self.data
 98    }
 99
100    fn basek(&self) -> usize {
101        self.basek
102    }
103
104    fn k(&self) -> usize {
105        self.k
106    }
107}
108
109impl<D: Data> GGSWCiphertext<D> {
110    pub fn rank(&self) -> usize {
111        self.data.cols_out() - 1
112    }
113
114    pub fn digits(&self) -> usize {
115        self.digits
116    }
117}
118
119use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
120
121impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> {
122    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
123        self.k = reader.read_u64::<LittleEndian>()? as usize;
124        self.basek = reader.read_u64::<LittleEndian>()? as usize;
125        self.digits = reader.read_u64::<LittleEndian>()? as usize;
126        self.data.read_from(reader)
127    }
128}
129
130impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
131    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
132        writer.write_u64::<LittleEndian>(self.k as u64)?;
133        writer.write_u64::<LittleEndian>(self.basek as u64)?;
134        writer.write_u64::<LittleEndian>(self.digits as u64)?;
135        self.data.write_to(writer)
136    }
137}