poulpy/poulpy-core/src/layouts/prepared/glwe_tensor_key.rs
poulpy-core/src/layouts/prepared/glwe_tensor_key.rsRaw
1use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
2
3use crate::layouts::{
4 Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWEPrepared, GGLWEPreparedFactory, GGLWEPreparedToMut, GGLWEPreparedToRef,
5 GLWEInfos, LWEInfos, Rank, TensorKey, TensorKeyToRef, TorusPrecision,
6};
7
8#[derive(PartialEq, Eq)]
9pub struct TensorKeyPrepared<D: Data, B: Backend> {
10 pub(crate) keys: Vec<GGLWEPrepared<D, B>>,
11}
12
13impl<D: Data, B: Backend> LWEInfos for TensorKeyPrepared<D, B> {
14 fn n(&self) -> Degree {
15 self.keys[0].n()
16 }
17
18 fn base2k(&self) -> Base2K {
19 self.keys[0].base2k()
20 }
21
22 fn k(&self) -> TorusPrecision {
23 self.keys[0].k()
24 }
25
26 fn size(&self) -> usize {
27 self.keys[0].size()
28 }
29}
30
31impl<D: Data, B: Backend> GLWEInfos for TensorKeyPrepared<D, B> {
32 fn rank(&self) -> Rank {
33 self.rank_out()
34 }
35}
36
37impl<D: Data, B: Backend> GGLWEInfos for TensorKeyPrepared<D, B> {
38 fn rank_in(&self) -> Rank {
39 self.rank_out()
40 }
41
42 fn rank_out(&self) -> Rank {
43 self.keys[0].rank_out()
44 }
45
46 fn dsize(&self) -> Dsize {
47 self.keys[0].dsize()
48 }
49
50 fn dnum(&self) -> Dnum {
51 self.keys[0].dnum()
52 }
53}
54
55pub trait TensorKeyPreparedFactory<B: Backend>
56where
57 Self: GGLWEPreparedFactory<B>,
58{
59 fn alloc_tensor_key_prepared(
60 &self,
61 base2k: Base2K,
62 k: TorusPrecision,
63 dnum: Dnum,
64 dsize: Dsize,
65 rank: Rank,
66 ) -> TensorKeyPrepared<Vec<u8>, B> {
67 let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
68 TensorKeyPrepared {
69 keys: (0..pairs)
70 .map(|_| self.alloc_gglwe_prepared(base2k, k, Rank(1), rank, dnum, dsize))
71 .collect(),
72 }
73 }
74
75 fn alloc_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> TensorKeyPrepared<Vec<u8>, B>
76 where
77 A: GGLWEInfos,
78 {
79 assert_eq!(
80 infos.rank_in(),
81 infos.rank_out(),
82 "rank_in != rank_out is not supported for TensorKeyPrepared"
83 );
84 self.alloc_tensor_key_prepared(
85 infos.base2k(),
86 infos.k(),
87 infos.dnum(),
88 infos.dsize(),
89 infos.rank_out(),
90 )
91 }
92
93 fn bytes_of_tensor_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
94 let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
95 pairs * self.bytes_of_gglwe_prepared(base2k, k, Rank(1), rank, dnum, dsize)
96 }
97
98 fn bytes_of_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> usize
99 where
100 A: GGLWEInfos,
101 {
102 self.bytes_of_tensor_key_prepared(
103 infos.base2k(),
104 infos.k(),
105 infos.rank(),
106 infos.dnum(),
107 infos.dsize(),
108 )
109 }
110
111 fn prepare_tensor_key_tmp_bytes<A>(&self, infos: &A) -> usize
112 where
113 A: GGLWEInfos,
114 {
115 self.prepare_gglwe_tmp_bytes(infos)
116 }
117
118 fn prepare_tensor_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
119 where
120 R: TensorKeyPreparedToMut<B>,
121 O: TensorKeyToRef,
122 {
123 let mut res: TensorKeyPrepared<&mut [u8], B> = res.to_mut();
124 let other: TensorKey<&[u8]> = other.to_ref();
125
126 assert_eq!(res.keys.len(), other.keys.len());
127
128 for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
129 self.prepare_gglwe(a, b, scratch);
130 }
131 }
132}
133
134impl<B: Backend> TensorKeyPreparedFactory<B> for Module<B> where Module<B>: GGLWEPreparedFactory<B> {}
135
136impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
137 pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
138 where
139 A: GGLWEInfos,
140 M: TensorKeyPreparedFactory<B>,
141 {
142 module.alloc_tensor_key_prepared_from_infos(infos)
143 }
144
145 pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
146 where
147 M: TensorKeyPreparedFactory<B>,
148 {
149 module.alloc_tensor_key_prepared(base2k, k, dnum, dsize, rank)
150 }
151
152 pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
153 where
154 A: GGLWEInfos,
155 M: TensorKeyPreparedFactory<B>,
156 {
157 module.bytes_of_tensor_key_prepared_from_infos(infos)
158 }
159
160 pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
161 where
162 M: TensorKeyPreparedFactory<B>,
163 {
164 module.bytes_of_tensor_key_prepared(base2k, k, rank, dnum, dsize)
165 }
166}
167
168impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
169 // Returns a mutable reference to GGLWE_{s}(s[i] * s[j])
170 pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWEPrepared<D, B> {
171 if i > j {
172 std::mem::swap(&mut i, &mut j);
173 };
174 let rank: usize = self.rank_out().into();
175 &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
176 }
177}
178
179impl<D: DataRef, B: Backend> TensorKeyPrepared<D, B> {
180 // Returns a reference to GGLWE_{s}(s[i] * s[j])
181 pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWEPrepared<D, B> {
182 if i > j {
183 std::mem::swap(&mut i, &mut j);
184 };
185 let rank: usize = self.rank_out().into();
186 &self.keys[i * rank + j - (i * (i + 1) / 2)]
187 }
188}
189
190impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
191 pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
192 where
193 A: GGLWEInfos,
194 M: TensorKeyPreparedFactory<B>,
195 {
196 module.prepare_tensor_key_tmp_bytes(infos)
197 }
198}
199
200impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
201 pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
202 where
203 O: TensorKeyToRef,
204 M: TensorKeyPreparedFactory<B>,
205 {
206 module.prepare_tensor_key(self, other, scratch);
207 }
208}
209
210pub trait TensorKeyPreparedToMut<B: Backend> {
211 fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B>;
212}
213
214impl<D: DataMut, B: Backend> TensorKeyPreparedToMut<B> for TensorKeyPrepared<D, B>
215where
216 GGLWEPrepared<D, B>: GGLWEPreparedToMut<B>,
217{
218 fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B> {
219 TensorKeyPrepared {
220 keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
221 }
222 }
223}
224
225pub trait TensorKeyPreparedToRef<B: Backend> {
226 fn to_ref(&self) -> TensorKeyPrepared<&[u8], B>;
227}
228
229impl<D: DataRef, B: Backend> TensorKeyPreparedToRef<B> for TensorKeyPrepared<D, B>
230where
231 GGLWEPrepared<D, B>: GGLWEPreparedToRef<B>,
232{
233 fn to_ref(&self) -> TensorKeyPrepared<&[u8], B> {
234 TensorKeyPrepared {
235 keys: self.keys.iter().map(|c| c.to_ref()).collect(),
236 }
237 }
238}