arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/layouts/compressed/gglwe_tsk.rs
core/src/layouts/compressed/gglwe_tsk.rsRaw
  1use backend::hal::{
  2    api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform},
  3    layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
  4};
  5
  6use crate::layouts::{
  7    GGLWETensorKey, Infos,
  8    compressed::{Decompress, GGLWESwitchingKeyCompressed},
  9};
 10use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 11use std::fmt;
 12
 13#[derive(PartialEq, Eq, Clone)]
 14pub struct GGLWETensorKeyCompressed<D: Data> {
 15    pub(crate) keys: Vec<GGLWESwitchingKeyCompressed<D>>,
 16}
 17
 18impl<D: DataRef> fmt::Debug for GGLWETensorKeyCompressed<D> {
 19    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 20        write!(f, "{}", self)
 21    }
 22}
 23
 24impl<D: DataMut> FillUniform for GGLWETensorKeyCompressed<D> {
 25    fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
 26        self.keys
 27            .iter_mut()
 28            .for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.fill_uniform(source))
 29    }
 30}
 31
 32impl<D: DataMut> Reset for GGLWETensorKeyCompressed<D>
 33where
 34    MatZnx<D>: Reset,
 35{
 36    fn reset(&mut self) {
 37        self.keys
 38            .iter_mut()
 39            .for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.reset())
 40    }
 41}
 42
 43impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> {
 44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 45        writeln!(f, "(GLWETensorKeyCompressed)",)?;
 46        for (i, key) in self.keys.iter().enumerate() {
 47            write!(f, "{}: {}", i, key)?;
 48        }
 49        Ok(())
 50    }
 51}
 52
 53impl GGLWETensorKeyCompressed<Vec<u8>> {
 54    pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
 55        let mut keys: Vec<GGLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new();
 56        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 57        (0..pairs).for_each(|_| {
 58            keys.push(GGLWESwitchingKeyCompressed::alloc(
 59                n, basek, k, rows, digits, 1, rank,
 60            ));
 61        });
 62        Self { keys: keys }
 63    }
 64
 65    pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
 66        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 67        pairs * GGLWESwitchingKeyCompressed::bytes_of(n, basek, k, rows, digits, 1)
 68    }
 69}
 70
 71impl<D: Data> Infos for GGLWETensorKeyCompressed<D> {
 72    type Inner = MatZnx<D>;
 73
 74    fn inner(&self) -> &Self::Inner {
 75        &self.keys[0].inner()
 76    }
 77
 78    fn basek(&self) -> usize {
 79        self.keys[0].basek()
 80    }
 81
 82    fn k(&self) -> usize {
 83        self.keys[0].k()
 84    }
 85}
 86
 87impl<D: Data> GGLWETensorKeyCompressed<D> {
 88    pub fn rank(&self) -> usize {
 89        self.keys[0].rank()
 90    }
 91
 92    pub fn digits(&self) -> usize {
 93        self.keys[0].digits()
 94    }
 95
 96    pub fn rank_in(&self) -> usize {
 97        self.keys[0].rank_in()
 98    }
 99
100    pub fn rank_out(&self) -> usize {
101        self.keys[0].rank_out()
102    }
103}
104
105impl<D: DataMut> ReaderFrom for GGLWETensorKeyCompressed<D> {
106    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
107        let len: usize = reader.read_u64::<LittleEndian>()? as usize;
108        if self.keys.len() != len {
109            return Err(std::io::Error::new(
110                std::io::ErrorKind::InvalidData,
111                format!("self.keys.len()={} != read len={}", self.keys.len(), len),
112            ));
113        }
114        for key in &mut self.keys {
115            key.read_from(reader)?;
116        }
117        Ok(())
118    }
119}
120
121impl<D: DataRef> WriterTo for GGLWETensorKeyCompressed<D> {
122    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
123        writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
124        for key in &self.keys {
125            key.write_to(writer)?;
126        }
127        Ok(())
128    }
129}
130
131impl<D: DataMut> GGLWETensorKeyCompressed<D> {
132    pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyCompressed<D> {
133        if i > j {
134            std::mem::swap(&mut i, &mut j);
135        };
136        let rank: usize = self.rank();
137        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
138    }
139}
140
141impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWETensorKeyCompressed<DR>> for GGLWETensorKey<D> {
142    fn decompress(&mut self, module: &Module<B>, other: &GGLWETensorKeyCompressed<DR>)
143    where
144        Module<B>: VecZnxFillUniform + VecZnxCopy,
145    {
146        #[cfg(debug_assertions)]
147        {
148            assert_eq!(
149                self.keys.len(),
150                other.keys.len(),
151                "invalid receiver: self.keys.len()={} != other.keys.len()={}",
152                self.keys.len(),
153                other.keys.len()
154            );
155        }
156
157        self.keys
158            .iter_mut()
159            .zip(other.keys.iter())
160            .for_each(|(a, b)| {
161                a.decompress(module, b);
162            });
163    }
164}