poulpy/poulpy-core/src/layouts/prepared/ggsw_ct.rs
poulpy-core/src/layouts/prepared/ggsw_ct.rsRaw
1use poulpy_hal::{
2 api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare, VmpPrepareTmpBytes},
3 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos},
4};
5
6use crate::layouts::{
7 Base2K, Degree, Dnum, Dsize, GGSW, GGSWInfos, GGSWToRef, GLWEInfos, GetDegree, LWEInfos, Rank, TorusPrecision,
8};
9
10#[derive(PartialEq, Eq)]
11pub struct GGSWPrepared<D: Data, B: Backend> {
12 pub(crate) data: VmpPMat<D, B>,
13 pub(crate) k: TorusPrecision,
14 pub(crate) base2k: Base2K,
15 pub(crate) dsize: Dsize,
16}
17
18impl<D: Data, B: Backend> LWEInfos for GGSWPrepared<D, B> {
19 fn n(&self) -> Degree {
20 Degree(self.data.n() as u32)
21 }
22
23 fn base2k(&self) -> Base2K {
24 self.base2k
25 }
26
27 fn k(&self) -> TorusPrecision {
28 self.k
29 }
30
31 fn size(&self) -> usize {
32 self.data.size()
33 }
34}
35
36impl<D: Data, B: Backend> GLWEInfos for GGSWPrepared<D, B> {
37 fn rank(&self) -> Rank {
38 Rank(self.data.cols_out() as u32 - 1)
39 }
40}
41
42impl<D: Data, B: Backend> GGSWInfos for GGSWPrepared<D, B> {
43 fn dsize(&self) -> Dsize {
44 self.dsize
45 }
46
47 fn dnum(&self) -> Dnum {
48 Dnum(self.data.rows() as u32)
49 }
50}
51
52pub trait GGSWPreparedAlloc<B: Backend>
53where
54 Self: GetDegree + VmpPMatAlloc<B> + VmpPMatAllocBytes,
55{
56 fn ggsw_prepared_alloc(
57 &self,
58 base2k: Base2K,
59 k: TorusPrecision,
60 dnum: Dnum,
61 dsize: Dsize,
62 rank: Rank,
63 ) -> GGSWPrepared<Vec<u8>, B> {
64 let size: usize = k.0.div_ceil(base2k.0) as usize;
65 debug_assert!(
66 size as u32 > dsize.0,
67 "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
68 dsize.0
69 );
70
71 assert!(
72 dnum.0 * dsize.0 <= size as u32,
73 "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
74 dnum.0,
75 dsize.0,
76 );
77
78 GGSWPrepared {
79 data: self.vmp_pmat_alloc(
80 dnum.into(),
81 (rank + 1).into(),
82 (rank + 1).into(),
83 k.0.div_ceil(base2k.0) as usize,
84 ),
85 k,
86 base2k,
87 dsize,
88 }
89 }
90
91 fn ggsw_prepared_alloc_from_infos<A>(&self, infos: &A) -> GGSWPrepared<Vec<u8>, B>
92 where
93 A: GGSWInfos,
94 {
95 assert_eq!(self.n(), infos.n());
96 self.ggsw_prepared_alloc(
97 infos.base2k(),
98 infos.k(),
99 infos.dnum(),
100 infos.dsize(),
101 infos.rank(),
102 )
103 }
104
105 fn ggsw_prepared_alloc_bytes(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize {
106 let size: usize = k.0.div_ceil(base2k.0) as usize;
107 debug_assert!(
108 size as u32 > dsize.0,
109 "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
110 dsize.0
111 );
112
113 assert!(
114 dnum.0 * dsize.0 <= size as u32,
115 "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
116 dnum.0,
117 dsize.0,
118 );
119
120 self.vmp_pmat_alloc_bytes(dnum.into(), (rank + 1).into(), (rank + 1).into(), size)
121 }
122
123 fn ggsw_prepared_alloc_bytes_from_infos<A>(&self, infos: &A) -> usize
124 where
125 A: GGSWInfos,
126 {
127 assert_eq!(self.n(), infos.n());
128 self.ggsw_prepared_alloc_bytes(
129 infos.base2k(),
130 infos.k(),
131 infos.dnum(),
132 infos.dsize(),
133 infos.rank(),
134 )
135 }
136}
137
138impl<B: Backend> GGSWPreparedAlloc<B> for Module<B> where Module<B>: GetDegree + VmpPMatAlloc<B> + VmpPMatAllocBytes {}
139
140impl<B: Backend> GGSWPrepared<Vec<u8>, B>
141where
142 Module<B>: GGSWPreparedAlloc<B>,
143{
144 pub fn alloc_from_infos<A>(module: &Module<B>, infos: &A) -> Self
145 where
146 A: GGSWInfos,
147 {
148 module.ggsw_prepared_alloc_from_infos(infos)
149 }
150
151 pub fn alloc(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self {
152 module.ggsw_prepared_alloc(base2k, k, dnum, dsize, rank)
153 }
154
155 pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
156 where
157 A: GGSWInfos,
158 {
159 module.ggsw_prepared_alloc_bytes_from_infos(infos)
160 }
161
162 pub fn alloc_bytes_with(
163 module: &Module<B>,
164 base2k: Base2K,
165 k: TorusPrecision,
166 dnum: Dnum,
167 dsize: Dsize,
168 rank: Rank,
169 ) -> usize {
170 module.ggsw_prepared_alloc_bytes(base2k, k, dnum, dsize, rank)
171 }
172}
173
174impl<D: DataRef, B: Backend> GGSWPrepared<D, B> {
175 pub fn data(&self) -> &VmpPMat<D, B> {
176 &self.data
177 }
178}
179
180pub trait GGSWPrepare<B: Backend>
181where
182 Self: GetDegree + VmpPrepareTmpBytes + VmpPrepare<B>,
183{
184 fn ggsw_prepare_tmp_bytes<A>(&self, infos: &A) -> usize
185 where
186 A: GGSWInfos,
187 {
188 assert_eq!(self.n(), infos.n());
189 self.vmp_prepare_tmp_bytes(
190 infos.dnum().into(),
191 (infos.rank() + 1).into(),
192 (infos.rank() + 1).into(),
193 infos.size(),
194 )
195 }
196 fn ggsw_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
197 where
198 R: GGSWPreparedToMut<B>,
199 O: GGSWToRef,
200 {
201 let mut res: GGSWPrepared<&mut [u8], B> = res.to_mut();
202 let other: GGSW<&[u8]> = other.to_ref();
203 assert_eq!(res.n(), self.n());
204 assert_eq!(other.n(), self.n());
205 assert_eq!(res.k, other.k);
206 assert_eq!(res.base2k, other.base2k);
207 assert_eq!(res.dsize, other.dsize);
208 self.vmp_prepare(&mut res.data, &other.data, scratch);
209 }
210}
211
212impl<B: Backend> GGSWPrepare<B> for Module<B> where Self: GetDegree + VmpPrepareTmpBytes + VmpPrepare<B> {}
213
214impl<B: Backend> GGSWPrepared<Vec<u8>, B>
215where
216 Module<B>: GGSWPrepare<B>,
217{
218 pub fn prepare_tmp_bytes<A>(&self, module: Module<B>, infos: &A) -> usize
219 where
220 A: GGSWInfos,
221 {
222 module.ggsw_prepare_tmp_bytes(infos)
223 }
224}
225
226impl<D: DataMut, B: Backend> GGSWPrepared<D, B>
227where
228 Module<B>: GGSWPrepare<B>,
229{
230 pub fn prepare<O>(&mut self, module: &Module<B>, other: &O, scratch: &mut Scratch<B>)
231 where
232 O: GGSWToRef,
233 {
234 module.ggsw_prepare(self, other, scratch);
235 }
236}
237
238pub trait GGSWPreparedToMut<B: Backend> {
239 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B>;
240}
241
242impl<D: DataMut, B: Backend> GGSWPreparedToMut<B> for GGSWPrepared<D, B> {
243 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B> {
244 GGSWPrepared {
245 base2k: self.base2k,
246 k: self.k,
247 dsize: self.dsize,
248 data: self.data.to_mut(),
249 }
250 }
251}
252
253pub trait GGSWCiphertextPreparedToRef<B: Backend> {
254 fn to_ref(&self) -> GGSWPrepared<&[u8], B>;
255}
256
257impl<D: DataRef, B: Backend> GGSWCiphertextPreparedToRef<B> for GGSWPrepared<D, B> {
258 fn to_ref(&self) -> GGSWPrepared<&[u8], B> {
259 GGSWPrepared {
260 base2k: self.base2k,
261 k: self.k,
262 dsize: self.dsize,
263 data: self.data.to_ref(),
264 }
265 }
266}