poulpy_core/layouts/prepared/
gglwe_tsk.rs1use poulpy_hal::{
2 api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
3 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
4};
5
6use crate::layouts::{
7 GGLWETensorKey, Infos,
8 prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
9};
10
11#[derive(PartialEq, Eq)]
12pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> {
13 pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>,
14}
15
16impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
17 pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
18 where
19 Module<B>: VmpPMatAlloc<B>,
20 {
21 let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new();
22 let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
23 (0..pairs).for_each(|_| {
24 keys.push(GGLWESwitchingKeyPrepared::alloc(
25 module, basek, k, rows, digits, 1, rank,
26 ));
27 });
28 Self { keys }
29 }
30
31 pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
32 where
33 Module<B>: VmpPMatAllocBytes,
34 {
35 let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
36 pairs * GGLWESwitchingKeyPrepared::bytes_of(module, basek, k, rows, digits, 1, rank)
37 }
38}
39
40impl<D: Data, B: Backend> Infos for GGLWETensorKeyPrepared<D, B> {
41 type Inner = VmpPMat<D, B>;
42
43 fn inner(&self) -> &Self::Inner {
44 self.keys[0].inner()
45 }
46
47 fn basek(&self) -> usize {
48 self.keys[0].basek()
49 }
50
51 fn k(&self) -> usize {
52 self.keys[0].k()
53 }
54}
55
56impl<D: Data, B: Backend> GGLWETensorKeyPrepared<D, B> {
57 pub fn rank(&self) -> usize {
58 self.keys[0].rank()
59 }
60
61 pub fn rank_in(&self) -> usize {
62 self.keys[0].rank_in()
63 }
64
65 pub fn rank_out(&self) -> usize {
66 self.keys[0].rank_out()
67 }
68
69 pub fn digits(&self) -> usize {
70 self.keys[0].digits()
71 }
72}
73
74impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> {
75 pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyPrepared<D, B> {
77 if i > j {
78 std::mem::swap(&mut i, &mut j);
79 };
80 let rank: usize = self.rank();
81 &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
82 }
83}
84
85impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> {
86 pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> {
88 if i > j {
89 std::mem::swap(&mut i, &mut j);
90 };
91 let rank: usize = self.rank();
92 &self.keys[i * rank + j - (i * (i + 1) / 2)]
93 }
94}
95
96impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B>
97where
98 Module<B>: VmpPrepare<B>,
99{
100 fn prepare(&mut self, module: &Module<B>, other: &GGLWETensorKey<DR>, scratch: &mut Scratch<B>) {
101 #[cfg(debug_assertions)]
102 {
103 assert_eq!(self.keys.len(), other.keys.len());
104 }
105 self.keys
106 .iter_mut()
107 .zip(other.keys.iter())
108 .for_each(|(a, b)| {
109 a.prepare(module, b, scratch);
110 });
111 }
112}
113
114impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D>
115where
116 Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
117{
118 fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWETensorKeyPrepared<Vec<u8>, B> {
119 let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(
120 module,
121 self.basek(),
122 self.k(),
123 self.rows(),
124 self.digits(),
125 self.rank(),
126 );
127 tsk_prepared.prepare(module, self, scratch);
128 tsk_prepared
129 }
130}