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