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 alloc_ggsw_prepared(
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 alloc_ggsw_prepared_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.alloc_ggsw_prepared(
97 infos.base2k(),
98 infos.k(),
99 infos.dnum(),
100 infos.dsize(),
101 infos.rank(),
102 )
103 }
104
105 fn bytes_of_ggsw_prepared(&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_bytes_of(dnum.into(), (rank + 1).into(), (rank + 1).into(), size)
121 }
122
123 fn bytes_of_ggsw_prepared_from_infos<A>(&self, infos: &A) -> usize
124 where
125 A: GGSWInfos,
126 {
127 assert_eq!(self.n(), infos.n());
128 self.bytes_of_ggsw_prepared(
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.alloc_ggsw_prepared_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.alloc_ggsw_prepared(base2k, k, dnum, dsize, rank)
153 }
154
155 pub fn bytes_of_from_infos<A>(module: &Module<B>, infos: &A) -> usize
156 where
157 A: GGSWInfos,
158 {
159 module.bytes_of_ggsw_prepared_from_infos(infos)
160 }
161
162 pub fn bytes_of(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize {
163 module.bytes_of_ggsw_prepared(base2k, k, dnum, dsize, rank)
164 }
165}
166
167impl<D: DataRef, B: Backend> GGSWPrepared<D, B> {
168 pub fn data(&self) -> &VmpPMat<D, B> {
169 &self.data
170 }
171}
172
173pub trait GGSWPrepare<B: Backend>
174where
175 Self: GetDegree + VmpPrepareTmpBytes + VmpPrepare<B>,
176{
177 fn ggsw_prepare_tmp_bytes<A>(&self, infos: &A) -> usize
178 where
179 A: GGSWInfos,
180 {
181 assert_eq!(self.n(), infos.n());
182 self.vmp_prepare_tmp_bytes(
183 infos.dnum().into(),
184 (infos.rank() + 1).into(),
185 (infos.rank() + 1).into(),
186 infos.size(),
187 )
188 }
189 fn ggsw_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
190 where
191 R: GGSWPreparedToMut<B>,
192 O: GGSWToRef,
193 {
194 let mut res: GGSWPrepared<&mut [u8], B> = res.to_mut();
195 let other: GGSW<&[u8]> = other.to_ref();
196 assert_eq!(res.n(), self.n());
197 assert_eq!(other.n(), self.n());
198 assert_eq!(res.k, other.k);
199 assert_eq!(res.base2k, other.base2k);
200 assert_eq!(res.dsize, other.dsize);
201 self.vmp_prepare(&mut res.data, &other.data, scratch);
202 }
203}
204
205impl<B: Backend> GGSWPrepare<B> for Module<B> where Self: GetDegree + VmpPrepareTmpBytes + VmpPrepare<B> {}
206
207impl<B: Backend> GGSWPrepared<Vec<u8>, B>
208where
209 Module<B>: GGSWPrepare<B>,
210{
211 pub fn prepare_tmp_bytes<A>(&self, module: Module<B>, infos: &A) -> usize
212 where
213 A: GGSWInfos,
214 {
215 module.ggsw_prepare_tmp_bytes(infos)
216 }
217}
218
219impl<D: DataMut, B: Backend> GGSWPrepared<D, B>
220where
221 Module<B>: GGSWPrepare<B>,
222{
223 pub fn prepare<O>(&mut self, module: &Module<B>, other: &O, scratch: &mut Scratch<B>)
224 where
225 O: GGSWToRef,
226 {
227 module.ggsw_prepare(self, other, scratch);
228 }
229}
230
231pub trait GGSWPreparedToMut<B: Backend> {
232 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B>;
233}
234
235impl<D: DataMut, B: Backend> GGSWPreparedToMut<B> for GGSWPrepared<D, B> {
236 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B> {
237 GGSWPrepared {
238 base2k: self.base2k,
239 k: self.k,
240 dsize: self.dsize,
241 data: self.data.to_mut(),
242 }
243 }
244}
245
246pub trait GGSWCiphertextPreparedToRef<B: Backend> {
247 fn to_ref(&self) -> GGSWPrepared<&[u8], B>;
248}
249
250impl<D: DataRef, B: Backend> GGSWCiphertextPreparedToRef<B> for GGSWPrepared<D, B> {
251 fn to_ref(&self) -> GGSWPrepared<&[u8], B> {
252 GGSWPrepared {
253 base2k: self.base2k,
254 k: self.k,
255 dsize: self.dsize,
256 data: self.data.to_ref(),
257 }
258 }
259}