poulpy/poulpy-core/src/layouts/prepared/ggsw_ct.rs
poulpy-core/src/layouts/prepared/ggsw_ct.rsRaw
1use poulpy_hal::{
2 api::{VmpPMatAlloc, VmpPMatBytesOf, VmpPrepare, VmpPrepareTmpBytes},
3 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos},
4};
5
6use crate::layouts::{
7 Base2K, Dnum, Dsize, GGSW, GGSWInfos, GGSWToRef, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, 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) -> RingDegree {
20 RingDegree(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: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf,
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.ring_degree(), 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.bytes_of_vmp_pmat(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.ring_degree(), 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 Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf {}
139
140impl<B: Backend> GGSWPrepared<Vec<u8>, B> {
141 pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
142 where
143 A: GGSWInfos,
144 M: GGSWPreparedAlloc<B>,
145 {
146 module.alloc_ggsw_prepared_from_infos(infos)
147 }
148
149 pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
150 where
151 M: GGSWPreparedAlloc<B>,
152 {
153 module.alloc_ggsw_prepared(base2k, k, dnum, dsize, rank)
154 }
155
156 pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
157 where
158 A: GGSWInfos,
159 M: GGSWPreparedAlloc<B>,
160 {
161 module.bytes_of_ggsw_prepared_from_infos(infos)
162 }
163
164 pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize
165 where
166 M: GGSWPreparedAlloc<B>,
167 {
168 module.bytes_of_ggsw_prepared(base2k, k, dnum, dsize, rank)
169 }
170}
171
172impl<D: DataRef, B: Backend> GGSWPrepared<D, B> {
173 pub fn data(&self) -> &VmpPMat<D, B> {
174 &self.data
175 }
176}
177
178pub trait GGSWPrepare<B: Backend>
179where
180 Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B>,
181{
182 fn ggsw_prepare_tmp_bytes<A>(&self, infos: &A) -> usize
183 where
184 A: GGSWInfos,
185 {
186 assert_eq!(self.ring_degree(), infos.n());
187 self.vmp_prepare_tmp_bytes(
188 infos.dnum().into(),
189 (infos.rank() + 1).into(),
190 (infos.rank() + 1).into(),
191 infos.size(),
192 )
193 }
194 fn ggsw_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
195 where
196 R: GGSWPreparedToMut<B>,
197 O: GGSWToRef,
198 {
199 let mut res: GGSWPrepared<&mut [u8], B> = res.to_mut();
200 let other: GGSW<&[u8]> = other.to_ref();
201 assert_eq!(res.n(), self.ring_degree());
202 assert_eq!(other.n(), self.ring_degree());
203 assert_eq!(res.k, other.k);
204 assert_eq!(res.base2k, other.base2k);
205 assert_eq!(res.dsize, other.dsize);
206 self.vmp_prepare(&mut res.data, &other.data, scratch);
207 }
208}
209
210impl<B: Backend> GGSWPrepare<B> for Module<B> where Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B> {}
211
212impl<B: Backend> GGSWPrepared<Vec<u8>, B> {
213 pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
214 where
215 A: GGSWInfos,
216 M: GGSWPrepare<B>,
217 {
218 module.ggsw_prepare_tmp_bytes(infos)
219 }
220}
221
222impl<D: DataMut, B: Backend> GGSWPrepared<D, B> {
223 pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
224 where
225 O: GGSWToRef,
226 M: GGSWPrepare<B>,
227 {
228 module.ggsw_prepare(self, other, scratch);
229 }
230}
231
232pub trait GGSWPreparedToMut<B: Backend> {
233 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B>;
234}
235
236impl<D: DataMut, B: Backend> GGSWPreparedToMut<B> for GGSWPrepared<D, B> {
237 fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B> {
238 GGSWPrepared {
239 base2k: self.base2k,
240 k: self.k,
241 dsize: self.dsize,
242 data: self.data.to_mut(),
243 }
244 }
245}
246
247pub trait GGSWPreparedToRef<B: Backend> {
248 fn to_ref(&self) -> GGSWPrepared<&[u8], B>;
249}
250
251impl<D: DataRef, B: Backend> GGSWPreparedToRef<B> for GGSWPrepared<D, B> {
252 fn to_ref(&self) -> GGSWPrepared<&[u8], B> {
253 GGSWPrepared {
254 base2k: self.base2k,
255 k: self.k,
256 dsize: self.dsize,
257 data: self.data.to_ref(),
258 }
259 }
260}