arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/gglwe/tensor_key.rs
core/src/gglwe/tensor_key.rsRaw
  1use backend::hal::{
  2    api::{MatZnxAlloc, MatZnxAllocBytes},
  3    layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, Scratch, VmpPMat, WriterTo},
  4};
  5
  6use crate::{GGLWEExecLayoutFamily, GLWESwitchingKey, GLWESwitchingKeyExec, Infos};
  7
  8#[derive(PartialEq, Eq)]
  9pub struct GLWETensorKey<D: Data> {
 10    pub(crate) keys: Vec<GLWESwitchingKey<D>>,
 11}
 12
 13impl GLWETensorKey<Vec<u8>> {
 14    pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
 15    where
 16        Module<B>: MatZnxAlloc,
 17    {
 18        let mut keys: Vec<GLWESwitchingKey<Vec<u8>>> = Vec::new();
 19        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 20        (0..pairs).for_each(|_| {
 21            keys.push(GLWESwitchingKey::alloc(
 22                module, basek, k, rows, digits, 1, rank,
 23            ));
 24        });
 25        Self { keys: keys }
 26    }
 27
 28    pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
 29    where
 30        Module<B>: MatZnxAllocBytes,
 31    {
 32        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 33        pairs * GLWESwitchingKey::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, 1, rank)
 34    }
 35}
 36
 37impl<D: Data> Infos for GLWETensorKey<D> {
 38    type Inner = MatZnx<D>;
 39
 40    fn inner(&self) -> &Self::Inner {
 41        &self.keys[0].inner()
 42    }
 43
 44    fn basek(&self) -> usize {
 45        self.keys[0].basek()
 46    }
 47
 48    fn k(&self) -> usize {
 49        self.keys[0].k()
 50    }
 51}
 52
 53impl<D: Data> GLWETensorKey<D> {
 54    pub fn rank(&self) -> usize {
 55        self.keys[0].rank()
 56    }
 57
 58    pub fn rank_in(&self) -> usize {
 59        self.keys[0].rank_in()
 60    }
 61
 62    pub fn rank_out(&self) -> usize {
 63        self.keys[0].rank_out()
 64    }
 65
 66    pub fn digits(&self) -> usize {
 67        self.keys[0].digits()
 68    }
 69}
 70
 71impl<D: DataMut> GLWETensorKey<D> {
 72    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
 73    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKey<D> {
 74        if i > j {
 75            std::mem::swap(&mut i, &mut j);
 76        };
 77        let rank: usize = self.rank();
 78        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
 79    }
 80}
 81
 82impl<D: DataRef> GLWETensorKey<D> {
 83    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
 84    pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey<D> {
 85        if i > j {
 86            std::mem::swap(&mut i, &mut j);
 87        };
 88        let rank: usize = self.rank();
 89        &self.keys[i * rank + j - (i * (i + 1) / 2)]
 90    }
 91}
 92
 93use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 94
 95impl<D: DataMut> ReaderFrom for GLWETensorKey<D> {
 96    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
 97        let len: usize = reader.read_u64::<LittleEndian>()? as usize;
 98        if self.keys.len() != len {
 99            return Err(std::io::Error::new(
100                std::io::ErrorKind::InvalidData,
101                format!("self.keys.len()={} != read len={}", self.keys.len(), len),
102            ));
103        }
104        for key in &mut self.keys {
105            key.read_from(reader)?;
106        }
107        Ok(())
108    }
109}
110
111impl<D: DataRef> WriterTo for GLWETensorKey<D> {
112    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
113        writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
114        for key in &self.keys {
115            key.write_to(writer)?;
116        }
117        Ok(())
118    }
119}
120
121#[derive(PartialEq, Eq)]
122pub struct GLWETensorKeyExec<D: Data, B: Backend> {
123    pub(crate) keys: Vec<GLWESwitchingKeyExec<D, B>>,
124}
125
126impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> {
127    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
128    where
129        Module<B>: GGLWEExecLayoutFamily<B>,
130    {
131        let mut keys: Vec<GLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new();
132        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
133        (0..pairs).for_each(|_| {
134            keys.push(GLWESwitchingKeyExec::alloc(
135                module, basek, k, rows, digits, 1, rank,
136            ));
137        });
138        Self { keys }
139    }
140
141    pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
142    where
143        Module<B>: GGLWEExecLayoutFamily<B>,
144    {
145        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
146        pairs * GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, 1, rank)
147    }
148}
149
150impl<D: Data, B: Backend> Infos for GLWETensorKeyExec<D, B> {
151    type Inner = VmpPMat<D, B>;
152
153    fn inner(&self) -> &Self::Inner {
154        &self.keys[0].inner()
155    }
156
157    fn basek(&self) -> usize {
158        self.keys[0].basek()
159    }
160
161    fn k(&self) -> usize {
162        self.keys[0].k()
163    }
164}
165
166impl<D: Data, B: Backend> GLWETensorKeyExec<D, B> {
167    pub fn rank(&self) -> usize {
168        self.keys[0].rank()
169    }
170
171    pub fn rank_in(&self) -> usize {
172        self.keys[0].rank_in()
173    }
174
175    pub fn rank_out(&self) -> usize {
176        self.keys[0].rank_out()
177    }
178
179    pub fn digits(&self) -> usize {
180        self.keys[0].digits()
181    }
182}
183
184impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
185    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
186    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyExec<D, B> {
187        if i > j {
188            std::mem::swap(&mut i, &mut j);
189        };
190        let rank: usize = self.rank();
191        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
192    }
193}
194
195impl<D: DataRef, B: Backend> GLWETensorKeyExec<D, B> {
196    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
197    pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyExec<D, B> {
198        if i > j {
199            std::mem::swap(&mut i, &mut j);
200        };
201        let rank: usize = self.rank();
202        &self.keys[i * rank + j - (i * (i + 1) / 2)]
203    }
204}
205
206impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
207    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWETensorKey<DataOther>, scratch: &mut Scratch<B>)
208    where
209        DataOther: DataRef,
210        Module<B>: GGLWEExecLayoutFamily<B>,
211    {
212        #[cfg(debug_assertions)]
213        {
214            assert_eq!(self.keys.len(), other.keys.len());
215        }
216        self.keys
217            .iter_mut()
218            .zip(other.keys.iter())
219            .for_each(|(a, b)| {
220                a.prepare(module, b, scratch);
221            });
222    }
223}