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