poulpy/poulpy-core/src/layouts/prepared/gglwe_tsk.rs
poulpy-core/src/layouts/prepared/gglwe_tsk.rsRaw
1use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
2
3use crate::layouts::{
4 Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWEPrepare, GGLWEPrepared, GGLWEPreparedAlloc, GGLWEPreparedToMut,
5 GGLWEPreparedToRef, 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 TensorKeyPreparedAlloc<B: Backend>
56where
57 Self: GGLWEPreparedAlloc<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
112impl<B: Backend> TensorKeyPreparedAlloc<B> for Module<B> where Module<B>: GGLWEPreparedAlloc<B> {}
113
114impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
115 pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
116 where
117 A: GGLWEInfos,
118 M: TensorKeyPreparedAlloc<B>,
119 {
120 module.alloc_tensor_key_prepared_from_infos(infos)
121 }
122
123 pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
124 where
125 M: TensorKeyPreparedAlloc<B>,
126 {
127 module.alloc_tensor_key_prepared(base2k, k, dnum, dsize, rank)
128 }
129
130 pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
131 where
132 A: GGLWEInfos,
133 M: TensorKeyPreparedAlloc<B>,
134 {
135 module.bytes_of_tensor_key_prepared_from_infos(infos)
136 }
137
138 pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
139 where
140 M: TensorKeyPreparedAlloc<B>,
141 {
142 module.bytes_of_tensor_key_prepared(base2k, k, rank, dnum, dsize)
143 }
144}
145
146impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
147 // Returns a mutable reference to GGLWE_{s}(s[i] * s[j])
148 pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWEPrepared<D, B> {
149 if i > j {
150 std::mem::swap(&mut i, &mut j);
151 };
152 let rank: usize = self.rank_out().into();
153 &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
154 }
155}
156
157impl<D: DataRef, B: Backend> TensorKeyPrepared<D, B> {
158 // Returns a reference to GGLWE_{s}(s[i] * s[j])
159 pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWEPrepared<D, B> {
160 if i > j {
161 std::mem::swap(&mut i, &mut j);
162 };
163 let rank: usize = self.rank_out().into();
164 &self.keys[i * rank + j - (i * (i + 1) / 2)]
165 }
166}
167
168pub trait TensorKeyPrepare<B: Backend>
169where
170 Self: GGLWEPrepare<B>,
171{
172 fn prepare_tensor_key_tmp_bytes<A>(&self, infos: &A) -> usize
173 where
174 A: GGLWEInfos,
175 {
176 self.prepare_gglwe_tmp_bytes(infos)
177 }
178
179 fn prepare_tensor_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
180 where
181 R: TensorKeyPreparedToMut<B>,
182 O: TensorKeyToRef,
183 {
184 let mut res: TensorKeyPrepared<&mut [u8], B> = res.to_mut();
185 let other: TensorKey<&[u8]> = other.to_ref();
186
187 assert_eq!(res.keys.len(), other.keys.len());
188
189 for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
190 self.prepare_gglwe(a, b, scratch);
191 }
192 }
193}
194
195impl<B: Backend> TensorKeyPrepare<B> for Module<B> where Self: GGLWEPrepare<B> {}
196
197impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
198 pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
199 where
200 A: GGLWEInfos,
201 M: TensorKeyPrepare<B>,
202 {
203 module.prepare_tensor_key_tmp_bytes(infos)
204 }
205}
206
207impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
208 pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
209 where
210 O: TensorKeyToRef,
211 M: TensorKeyPrepare<B>,
212 {
213 module.prepare_tensor_key(self, other, scratch);
214 }
215}
216
217pub trait TensorKeyPreparedToMut<B: Backend> {
218 fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B>;
219}
220
221impl<D: DataMut, B: Backend> TensorKeyPreparedToMut<B> for TensorKeyPrepared<D, B>
222where
223 GGLWEPrepared<D, B>: GGLWEPreparedToMut<B>,
224{
225 fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B> {
226 TensorKeyPrepared {
227 keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
228 }
229 }
230}
231
232pub trait TensorKeyPreparedToRef<B: Backend> {
233 fn to_ref(&self) -> TensorKeyPrepared<&[u8], B>;
234}
235
236impl<D: DataRef, B: Backend> TensorKeyPreparedToRef<B> for TensorKeyPrepared<D, B>
237where
238 GGLWEPrepared<D, B>: GGLWEPreparedToRef<B>,
239{
240 fn to_ref(&self) -> TensorKeyPrepared<&[u8], B> {
241 TensorKeyPrepared {
242 keys: self.keys.iter().map(|c| c.to_ref()).collect(),
243 }
244 }
245}