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