arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/gglwe/layouts_exec.rs
core/src/gglwe/layouts_exec.rsRaw
  1use backend::hal::{
  2    api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
  4};
  5
  6use crate::{AutomorphismKey, GGLWECiphertext, GGLWEExecLayoutFamily, GLWESwitchingKey, GLWETensorKey, Infos};
  7
  8#[derive(PartialEq, Eq)]
  9pub struct GGLWECiphertextExec<D: Data, B: Backend> {
 10    pub(crate) data: VmpPMat<D, B>,
 11    pub(crate) basek: usize,
 12    pub(crate) k: usize,
 13    pub(crate) digits: usize,
 14}
 15
 16impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
 17    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
 18    where
 19        Module<B>: GGLWEExecLayoutFamily<B>,
 20    {
 21        let size: usize = k.div_ceil(basek);
 22        debug_assert!(
 23            size > digits,
 24            "invalid gglwe: ceil(k/basek): {} <= digits: {}",
 25            size,
 26            digits
 27        );
 28
 29        assert!(
 30            rows * digits <= size,
 31            "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
 32            rows,
 33            digits,
 34            size
 35        );
 36
 37        Self {
 38            data: module.vmp_pmat_alloc(rows, rank_in, rank_out + 1, size),
 39            basek: basek,
 40            k,
 41            digits,
 42        }
 43    }
 44
 45    pub fn bytes_of(
 46        module: &Module<B>,
 47        basek: usize,
 48        k: usize,
 49        rows: usize,
 50        digits: usize,
 51        rank_in: usize,
 52        rank_out: usize,
 53    ) -> usize
 54    where
 55        Module<B>: GGLWEExecLayoutFamily<B>,
 56    {
 57        let size: usize = k.div_ceil(basek);
 58        debug_assert!(
 59            size > digits,
 60            "invalid gglwe: ceil(k/basek): {} <= digits: {}",
 61            size,
 62            digits
 63        );
 64
 65        assert!(
 66            rows * digits <= size,
 67            "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}",
 68            rows,
 69            digits,
 70            size
 71        );
 72
 73        module.vmp_pmat_alloc_bytes(rows, rank_in, rank_out + 1, rows)
 74    }
 75}
 76
 77impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> {
 78    type Inner = VmpPMat<D, B>;
 79
 80    fn inner(&self) -> &Self::Inner {
 81        &self.data
 82    }
 83
 84    fn basek(&self) -> usize {
 85        self.basek
 86    }
 87
 88    fn k(&self) -> usize {
 89        self.k
 90    }
 91}
 92
 93impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> {
 94    pub fn rank(&self) -> usize {
 95        self.data.cols_out() - 1
 96    }
 97
 98    pub fn digits(&self) -> usize {
 99        self.digits
100    }
101
102    pub fn rank_in(&self) -> usize {
103        self.data.cols_in()
104    }
105
106    pub fn rank_out(&self) -> usize {
107        self.data.cols_out() - 1
108    }
109}
110
111impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> {
112    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>)
113    where
114        DataOther: DataRef,
115        Module<B>: GGLWEExecLayoutFamily<B>,
116    {
117        module.vmp_prepare(&mut self.data, &other.data, scratch);
118        self.basek = other.basek;
119        self.k = other.k;
120        self.digits = other.digits;
121    }
122}
123
124#[derive(PartialEq, Eq)]
125pub struct GLWESwitchingKeyExec<D: Data, B: Backend> {
126    pub(crate) key: GGLWECiphertextExec<D, B>,
127    pub(crate) sk_in_n: usize,  // Degree of sk_in
128    pub(crate) sk_out_n: usize, // Degree of sk_out
129}
130
131impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
132    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
133    where
134        Module<B>: GGLWEExecLayoutFamily<B>,
135    {
136        GLWESwitchingKeyExec::<Vec<u8>, B> {
137            key: GGLWECiphertextExec::alloc(module, basek, k, rows, digits, rank_in, rank_out),
138            sk_in_n: 0,
139            sk_out_n: 0,
140        }
141    }
142
143    pub fn bytes_of(
144        module: &Module<B>,
145        basek: usize,
146        k: usize,
147        rows: usize,
148        digits: usize,
149        rank_in: usize,
150        rank_out: usize,
151    ) -> usize
152    where
153        Module<B>: GGLWEExecLayoutFamily<B>,
154    {
155        GGLWECiphertextExec::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
156    }
157
158    pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
159    where
160        Module<B>: GGLWEExecLayoutFamily<B>,
161    {
162        let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
163            module,
164            other.basek(),
165            other.k(),
166            other.rows(),
167            other.digits(),
168            other.rank_in(),
169            other.rank_out(),
170        );
171        ksk_exec.prepare(module, other, scratch);
172        ksk_exec
173    }
174}
175
176impl<D: Data, B: Backend> Infos for GLWESwitchingKeyExec<D, B> {
177    type Inner = VmpPMat<D, B>;
178
179    fn inner(&self) -> &Self::Inner {
180        self.key.inner()
181    }
182
183    fn basek(&self) -> usize {
184        self.key.basek()
185    }
186
187    fn k(&self) -> usize {
188        self.key.k()
189    }
190}
191
192impl<D: Data, B: Backend> GLWESwitchingKeyExec<D, B> {
193    pub fn rank(&self) -> usize {
194        self.key.data.cols_out() - 1
195    }
196
197    pub fn rank_in(&self) -> usize {
198        self.key.data.cols_in()
199    }
200
201    pub fn rank_out(&self) -> usize {
202        self.key.data.cols_out() - 1
203    }
204
205    pub fn digits(&self) -> usize {
206        self.key.digits()
207    }
208
209    pub fn sk_degree_in(&self) -> usize {
210        self.sk_in_n
211    }
212
213    pub fn sk_degree_out(&self) -> usize {
214        self.sk_out_n
215    }
216}
217
218impl<D: DataMut, B: Backend> GLWESwitchingKeyExec<D, B> {
219    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
220    where
221        DataOther: DataRef,
222        Module<B>: GGLWEExecLayoutFamily<B>,
223    {
224        self.key.prepare(module, &other.key, scratch);
225        self.sk_in_n = other.sk_in_n;
226        self.sk_out_n = other.sk_out_n;
227    }
228}
229
230#[derive(PartialEq, Eq)]
231pub struct AutomorphismKeyExec<D: Data, B: Backend> {
232    pub(crate) key: GLWESwitchingKeyExec<D, B>,
233    pub(crate) p: i64,
234}
235
236impl<B: Backend> AutomorphismKeyExec<Vec<u8>, B> {
237    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
238    where
239        Module<B>: GGLWEExecLayoutFamily<B>,
240    {
241        AutomorphismKeyExec::<Vec<u8>, B> {
242            key: GLWESwitchingKeyExec::alloc(module, basek, k, rows, digits, rank, rank),
243            p: 0,
244        }
245    }
246
247    pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
248    where
249        Module<B>: GGLWEExecLayoutFamily<B>,
250    {
251        GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, rank, rank)
252    }
253
254    pub fn from<DataOther: DataRef>(module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self
255    where
256        Module<B>: GGLWEExecLayoutFamily<B>,
257    {
258        let mut atk_exec: AutomorphismKeyExec<Vec<u8>, B> = Self::alloc(
259            module,
260            other.basek(),
261            other.k(),
262            other.rows(),
263            other.digits(),
264            other.rank(),
265        );
266        atk_exec.prepare(module, other, scratch);
267        atk_exec
268    }
269}
270
271impl<D: DataMut, B: Backend> AutomorphismKeyExec<D, B> {
272    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>)
273    where
274        DataOther: DataRef,
275        Module<B>: GGLWEExecLayoutFamily<B>,
276    {
277        self.key.prepare(module, &other.key, scratch);
278        self.p = other.p;
279    }
280}
281
282impl<D: Data, B: Backend> Infos for AutomorphismKeyExec<D, B> {
283    type Inner = VmpPMat<D, B>;
284
285    fn inner(&self) -> &Self::Inner {
286        &self.key.inner()
287    }
288
289    fn basek(&self) -> usize {
290        self.key.basek()
291    }
292
293    fn k(&self) -> usize {
294        self.key.k()
295    }
296}
297
298impl<D: Data, B: Backend> AutomorphismKeyExec<D, B> {
299    pub fn p(&self) -> i64 {
300        self.p
301    }
302
303    pub fn digits(&self) -> usize {
304        self.key.digits()
305    }
306
307    pub fn rank(&self) -> usize {
308        self.key.rank()
309    }
310
311    pub fn rank_in(&self) -> usize {
312        self.key.rank_in()
313    }
314
315    pub fn rank_out(&self) -> usize {
316        self.key.rank_out()
317    }
318}
319
320#[derive(PartialEq, Eq)]
321pub struct GLWETensorKeyExec<D: Data, B: Backend> {
322    pub(crate) keys: Vec<GLWESwitchingKeyExec<D, B>>,
323}
324
325impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> {
326    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
327    where
328        Module<B>: GGLWEExecLayoutFamily<B>,
329    {
330        let mut keys: Vec<GLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new();
331        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
332        (0..pairs).for_each(|_| {
333            keys.push(GLWESwitchingKeyExec::alloc(
334                module, basek, k, rows, digits, 1, rank,
335            ));
336        });
337        Self { keys }
338    }
339
340    pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
341    where
342        Module<B>: GGLWEExecLayoutFamily<B>,
343    {
344        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
345        pairs * GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, 1, rank)
346    }
347}
348
349impl<D: Data, B: Backend> Infos for GLWETensorKeyExec<D, B> {
350    type Inner = VmpPMat<D, B>;
351
352    fn inner(&self) -> &Self::Inner {
353        &self.keys[0].inner()
354    }
355
356    fn basek(&self) -> usize {
357        self.keys[0].basek()
358    }
359
360    fn k(&self) -> usize {
361        self.keys[0].k()
362    }
363}
364
365impl<D: Data, B: Backend> GLWETensorKeyExec<D, B> {
366    pub fn rank(&self) -> usize {
367        self.keys[0].rank()
368    }
369
370    pub fn rank_in(&self) -> usize {
371        self.keys[0].rank_in()
372    }
373
374    pub fn rank_out(&self) -> usize {
375        self.keys[0].rank_out()
376    }
377
378    pub fn digits(&self) -> usize {
379        self.keys[0].digits()
380    }
381}
382
383impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
384    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
385    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyExec<D, B> {
386        if i > j {
387            std::mem::swap(&mut i, &mut j);
388        };
389        let rank: usize = self.rank();
390        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
391    }
392}
393
394impl<D: DataRef, B: Backend> GLWETensorKeyExec<D, B> {
395    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
396    pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyExec<D, B> {
397        if i > j {
398            std::mem::swap(&mut i, &mut j);
399        };
400        let rank: usize = self.rank();
401        &self.keys[i * rank + j - (i * (i + 1) / 2)]
402    }
403}
404
405impl<D: DataMut, B: Backend> GLWETensorKeyExec<D, B> {
406    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWETensorKey<DataOther>, scratch: &mut Scratch<B>)
407    where
408        DataOther: DataRef,
409        Module<B>: GGLWEExecLayoutFamily<B>,
410    {
411        #[cfg(debug_assertions)]
412        {
413            assert_eq!(self.keys.len(), other.keys.len());
414        }
415        self.keys
416            .iter_mut()
417            .zip(other.keys.iter())
418            .for_each(|(a, b)| {
419                a.prepare(module, b, scratch);
420            });
421    }
422}