arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/compressed/gglwe_tsk.rs
poulpy-core/src/layouts/compressed/gglwe_tsk.rsRaw
  1use poulpy_hal::{
  2    layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
  3    source::Source,
  4};
  5
  6use crate::layouts::{
  7    Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TensorKey, TensorKeyToMut, TorusPrecision,
  8    compressed::{
  9        GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedToMut, GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
 10    },
 11};
 12use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 13use std::fmt;
 14
 15#[derive(PartialEq, Eq, Clone)]
 16pub struct TensorKeyCompressed<D: Data> {
 17    pub(crate) keys: Vec<GLWESwitchingKeyCompressed<D>>,
 18}
 19
 20impl<D: Data> LWEInfos for TensorKeyCompressed<D> {
 21    fn n(&self) -> Degree {
 22        self.keys[0].n()
 23    }
 24
 25    fn base2k(&self) -> Base2K {
 26        self.keys[0].base2k()
 27    }
 28
 29    fn k(&self) -> TorusPrecision {
 30        self.keys[0].k()
 31    }
 32    fn size(&self) -> usize {
 33        self.keys[0].size()
 34    }
 35}
 36impl<D: Data> GLWEInfos for TensorKeyCompressed<D> {
 37    fn rank(&self) -> Rank {
 38        self.rank_out()
 39    }
 40}
 41
 42impl<D: Data> GGLWEInfos for TensorKeyCompressed<D> {
 43    fn rank_in(&self) -> Rank {
 44        self.rank_out()
 45    }
 46
 47    fn rank_out(&self) -> Rank {
 48        self.keys[0].rank_out()
 49    }
 50
 51    fn dsize(&self) -> Dsize {
 52        self.keys[0].dsize()
 53    }
 54
 55    fn dnum(&self) -> Dnum {
 56        self.keys[0].dnum()
 57    }
 58}
 59
 60impl<D: DataRef> fmt::Debug for TensorKeyCompressed<D> {
 61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 62        write!(f, "{self}")
 63    }
 64}
 65
 66impl<D: DataMut> FillUniform for TensorKeyCompressed<D> {
 67    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
 68        self.keys
 69            .iter_mut()
 70            .for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.fill_uniform(log_bound, source))
 71    }
 72}
 73
 74impl<D: DataRef> fmt::Display for TensorKeyCompressed<D> {
 75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 76        writeln!(f, "(GLWETensorKeyCompressed)",)?;
 77        for (i, key) in self.keys.iter().enumerate() {
 78            write!(f, "{i}: {key}")?;
 79        }
 80        Ok(())
 81    }
 82}
 83
 84impl TensorKeyCompressed<Vec<u8>> {
 85    pub fn alloc_from_infos<A>(infos: &A) -> Self
 86    where
 87        A: GGLWEInfos,
 88    {
 89        Self::alloc(
 90            infos.n(),
 91            infos.base2k(),
 92            infos.k(),
 93            infos.rank(),
 94            infos.dnum(),
 95            infos.dsize(),
 96        )
 97    }
 98
 99    pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
100        let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
101        TensorKeyCompressed {
102            keys: (0..pairs)
103                .map(|_| GLWESwitchingKeyCompressed::alloc(n, base2k, k, Rank(1), rank, dnum, dsize))
104                .collect(),
105        }
106    }
107
108    pub fn bytes_of_from_infos<A>(infos: &A) -> usize
109    where
110        A: GGLWEInfos,
111    {
112        Self::bytes_of(
113            infos.n(),
114            infos.base2k(),
115            infos.k(),
116            infos.rank(),
117            infos.dnum(),
118            infos.dsize(),
119        )
120    }
121
122    pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
123        let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
124        pairs * GLWESwitchingKeyCompressed::bytes_of(n, base2k, k, Rank(1), dnum, dsize)
125    }
126}
127
128impl<D: DataMut> ReaderFrom for TensorKeyCompressed<D> {
129    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
130        let len: usize = reader.read_u64::<LittleEndian>()? as usize;
131        if self.keys.len() != len {
132            return Err(std::io::Error::new(
133                std::io::ErrorKind::InvalidData,
134                format!("self.keys.len()={} != read len={}", self.keys.len(), len),
135            ));
136        }
137        for key in &mut self.keys {
138            key.read_from(reader)?;
139        }
140        Ok(())
141    }
142}
143
144impl<D: DataRef> WriterTo for TensorKeyCompressed<D> {
145    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
146        writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
147        for key in &self.keys {
148            key.write_to(writer)?;
149        }
150        Ok(())
151    }
152}
153
154impl<D: DataMut> TensorKeyCompressed<D> {
155    pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyCompressed<D> {
156        if i > j {
157            std::mem::swap(&mut i, &mut j);
158        };
159        let rank: usize = self.rank_out().into();
160        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
161    }
162}
163
164pub trait TensorKeyDecompress
165where
166    Self: GLWESwitchingKeyDecompress,
167{
168    fn decompress_tensor_key<R, O>(&self, res: &mut R, other: &O)
169    where
170        R: TensorKeyToMut,
171        O: TensorKeyCompressedToRef,
172    {
173        let res: &mut TensorKey<&mut [u8]> = &mut res.to_mut();
174        let other: &TensorKeyCompressed<&[u8]> = &other.to_ref();
175
176        assert_eq!(
177            res.keys.len(),
178            other.keys.len(),
179            "invalid receiver: res.keys.len()={} != other.keys.len()={}",
180            res.keys.len(),
181            other.keys.len()
182        );
183
184        for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
185            self.decompress_glwe_switching_key(a, b);
186        }
187    }
188}
189
190impl<B: Backend> TensorKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
191
192impl<D: DataMut> TensorKey<D> {
193    pub fn decompress<O, M>(&mut self, module: &M, other: &O)
194    where
195        O: TensorKeyCompressedToRef,
196        M: TensorKeyDecompress,
197    {
198        module.decompress_tensor_key(self, other);
199    }
200}
201
202pub trait TensorKeyCompressedToMut {
203    fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]>;
204}
205
206impl<D: DataMut> TensorKeyCompressedToMut for TensorKeyCompressed<D>
207where
208    GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
209{
210    fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]> {
211        TensorKeyCompressed {
212            keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
213        }
214    }
215}
216
217pub trait TensorKeyCompressedToRef {
218    fn to_ref(&self) -> TensorKeyCompressed<&[u8]>;
219}
220
221impl<D: DataRef> TensorKeyCompressedToRef for TensorKeyCompressed<D>
222where
223    GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
224{
225    fn to_ref(&self) -> TensorKeyCompressed<&[u8]> {
226        TensorKeyCompressed {
227            keys: self.keys.iter().map(|c| c.to_ref()).collect(),
228        }
229    }
230}