arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/elem.rs
core/src/elem.rsRaw
  1use base2k::{
  2    Backend, FFT64, MatZnxDft, MatZnxDftToRef, Module, Scratch, VecZnx, VecZnxAlloc, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps,
  3    VecZnxDftToMut, VecZnxDftToRef, VecZnxToMut, VecZnxToRef, ZnxInfos, ZnxZero,
  4};
  5
  6use crate::{
  7    grlwe::GRLWECt,
  8    rgsw::RGSWCt,
  9    rlwe::{RLWECt, RLWECtDft},
 10    utils::derive_size,
 11};
 12
 13pub trait Infos {
 14    type Inner: ZnxInfos;
 15
 16    fn inner(&self) -> &Self::Inner;
 17
 18    /// Returns the ring degree of the polynomials.
 19    fn n(&self) -> usize {
 20        self.inner().n()
 21    }
 22
 23    /// Returns the base two logarithm of the ring dimension of the polynomials.
 24    fn log_n(&self) -> usize {
 25        self.inner().log_n()
 26    }
 27
 28    /// Returns the number of rows.
 29    fn rows(&self) -> usize {
 30        self.inner().rows()
 31    }
 32
 33    /// Returns the number of polynomials in each row.
 34    fn cols(&self) -> usize {
 35        self.inner().cols()
 36    }
 37
 38    /// Returns the number of size per polynomial.
 39    fn size(&self) -> usize {
 40        let size: usize = self.inner().size();
 41        debug_assert_eq!(size, derive_size(self.log_base2k(), self.log_k()));
 42        size
 43    }
 44
 45    /// Returns the total number of small polynomials.
 46    fn poly_count(&self) -> usize {
 47        self.rows() * self.cols() * self.size()
 48    }
 49
 50    /// Returns the base 2 logarithm of the ciphertext base.
 51    fn log_base2k(&self) -> usize;
 52
 53    /// Returns the bit precision of the ciphertext.
 54    fn log_k(&self) -> usize;
 55}
 56
 57pub trait GetRow<B: Backend> {
 58    fn get_row<R>(&self, module: &Module<B>, row_i: usize, col_j: usize, res: &mut RLWECtDft<R, B>)
 59    where
 60        VecZnxDft<R, B>: VecZnxDftToMut<B>;
 61}
 62
 63pub trait SetRow<B: Backend> {
 64    fn set_row<A>(&mut self, module: &Module<B>, row_i: usize, col_j: usize, a: &RLWECtDft<A, B>)
 65    where
 66        VecZnxDft<A, B>: VecZnxDftToRef<B>;
 67}
 68
 69pub trait ProdByScratchSpace {
 70    fn prod_by_grlwe_scratch_space(module: &Module<FFT64>, lhs: usize, rhs: usize) -> usize;
 71    fn prod_by_rgsw_scratch_space(module: &Module<FFT64>, lhs: usize, rhs: usize) -> usize;
 72}
 73
 74pub trait ProdBy<D> {
 75    fn prod_by_grlwe<R>(&mut self, module: &Module<FFT64>, rhs: &GRLWECt<R, FFT64>, scratch: &mut Scratch)
 76    where
 77        MatZnxDft<R, FFT64>: MatZnxDftToRef<FFT64>;
 78
 79    fn prod_by_rgsw<R>(&mut self, module: &Module<FFT64>, rhs: &RGSWCt<R, FFT64>, scratch: &mut Scratch)
 80    where
 81        MatZnxDft<R, FFT64>: MatZnxDftToRef<FFT64>;
 82}
 83
 84pub trait FromProdByScratchSpace {
 85    fn from_prod_by_grlwe_scratch_space(module: &Module<FFT64>, res_size: usize, lhs: usize, rhs: usize) -> usize;
 86    fn from_prod_by_rgsw_scratch_space(module: &Module<FFT64>, res_size: usize, lhs: usize, rhs: usize) -> usize;
 87}
 88
 89pub trait FromProdBy<D, L> {
 90    fn from_prod_by_grlwe<R>(&mut self, module: &Module<FFT64>, lhs: &L, rhs: &GRLWECt<R, FFT64>, scratch: &mut Scratch)
 91    where
 92        MatZnxDft<R, FFT64>: MatZnxDftToRef<FFT64>;
 93
 94    fn from_prod_by_rgsw<R>(&mut self, module: &Module<FFT64>, lhs: &L, rhs: &RGSWCt<R, FFT64>, scratch: &mut Scratch)
 95    where
 96        MatZnxDft<R, FFT64>: MatZnxDftToRef<FFT64>;
 97}
 98
 99pub(crate) trait MatZnxDftProducts<D, C>: Infos
100where
101    MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
102{
103    fn mul_rlwe<R, A>(&self, module: &Module<FFT64>, res: &mut RLWECt<R>, a: &RLWECt<A>, scratch: &mut Scratch)
104    where
105        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64>,
106        VecZnx<R>: VecZnxToMut,
107        VecZnx<A>: VecZnxToRef;
108
109    fn mul_rlwe_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize;
110
111    fn mul_rlwe_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, mat_size: usize) -> usize {
112        Self::mul_rlwe_scratch_space(module, res_size, res_size, mat_size)
113    }
114
115    fn mul_rlwe_dft_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, mat_size: usize) -> usize {
116        (Self::mul_rlwe_scratch_space(module, res_size, a_size, mat_size) | module.vec_znx_idft_tmp_bytes())
117            + module.bytes_of_vec_znx(2, a_size)
118            + module.bytes_of_vec_znx(2, res_size)
119    }
120
121    fn mul_rlwe_dft_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, mat_size: usize) -> usize {
122        (Self::mul_rlwe_inplace_scratch_space(module, res_size, mat_size) | module.vec_znx_idft_tmp_bytes())
123            + module.bytes_of_vec_znx(2, res_size)
124    }
125
126    fn mul_mat_rlwe_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, mat_size: usize) -> usize {
127        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, mat_size) + module.bytes_of_vec_znx_dft(2, a_size)
128    }
129
130    fn mul_mat_rlwe_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, mat_size: usize) -> usize {
131        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, mat_size) + module.bytes_of_vec_znx_dft(2, res_size)
132    }
133
134    fn mul_rlwe_inplace<R>(&self, module: &Module<FFT64>, res: &mut RLWECt<R>, scratch: &mut Scratch)
135    where
136        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
137        VecZnx<R>: VecZnxToMut + VecZnxToRef,
138    {
139        unsafe {
140            let res_ptr: *mut RLWECt<R> = res as *mut RLWECt<R>; // This is ok because [Self::mul_rlwe] only updates res at the end.
141            self.mul_rlwe(&module, &mut *res_ptr, &*res_ptr, scratch);
142        }
143    }
144
145    fn mul_rlwe_dft<R, A>(
146        &self,
147        module: &Module<FFT64>,
148        res: &mut RLWECtDft<R, FFT64>,
149        a: &RLWECtDft<A, FFT64>,
150        scratch: &mut Scratch,
151    ) where
152        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
153        VecZnxDft<R, FFT64>: VecZnxDftToMut<FFT64> + VecZnxDftToRef<FFT64> + ZnxInfos,
154        VecZnxDft<A, FFT64>: VecZnxDftToRef<FFT64> + ZnxInfos,
155    {
156        let log_base2k: usize = self.log_base2k();
157
158        #[cfg(debug_assertions)]
159        {
160            assert_eq!(res.log_base2k(), log_base2k);
161            assert_eq!(self.n(), module.n());
162            assert_eq!(res.n(), module.n());
163        }
164
165        let (a_data, scratch_1) = scratch.tmp_vec_znx(module, 2, a.size());
166
167        let mut a_idft: RLWECt<&mut [u8]> = RLWECt::<&mut [u8]> {
168            data: a_data,
169            log_base2k: a.log_base2k(),
170            log_k: a.log_k(),
171        };
172
173        a.idft(module, &mut a_idft, scratch_1);
174
175        let (res_data, scratch_2) = scratch_1.tmp_vec_znx(module, 2, res.size());
176
177        let mut res_idft: RLWECt<&mut [u8]> = RLWECt::<&mut [u8]> {
178            data: res_data,
179            log_base2k: res.log_base2k(),
180            log_k: res.log_k(),
181        };
182
183        self.mul_rlwe(module, &mut res_idft, &a_idft, scratch_2);
184
185        module.vec_znx_dft(res, 0, &res_idft, 0);
186        module.vec_znx_dft(res, 1, &res_idft, 1);
187    }
188
189    fn mul_rlwe_dft_inplace<R>(&self, module: &Module<FFT64>, res: &mut RLWECtDft<R, FFT64>, scratch: &mut Scratch)
190    where
191        VecZnxDft<R, FFT64>: VecZnxDftToRef<FFT64> + VecZnxDftToMut<FFT64>,
192    {
193        let log_base2k: usize = self.log_base2k();
194
195        #[cfg(debug_assertions)]
196        {
197            assert_eq!(res.log_base2k(), log_base2k);
198            assert_eq!(self.n(), module.n());
199            assert_eq!(res.n(), module.n());
200        }
201
202        let (res_data, scratch_1) = scratch.tmp_vec_znx(module, 2, res.size());
203
204        let mut res_idft: RLWECt<&mut [u8]> = RLWECt::<&mut [u8]> {
205            data: res_data,
206            log_base2k: res.log_base2k(),
207            log_k: res.log_k(),
208        };
209
210        res.idft(module, &mut res_idft, scratch_1);
211
212        self.mul_rlwe_inplace(module, &mut res_idft, scratch_1);
213
214        module.vec_znx_dft(res, 0, &res_idft, 0);
215        module.vec_znx_dft(res, 1, &res_idft, 1);
216    }
217
218    fn mul_mat_rlwe<R, A>(&self, module: &Module<FFT64>, res: &mut R, a: &A, scratch: &mut Scratch)
219    where
220        A: GetRow<FFT64> + Infos,
221        R: SetRow<FFT64> + Infos,
222    {
223        let (tmp_row_data, scratch1) = scratch.tmp_vec_znx_dft(module, 2, a.size());
224
225        let mut tmp_row: RLWECtDft<&mut [u8], FFT64> = RLWECtDft::<&mut [u8], FFT64> {
226            data: tmp_row_data,
227            log_base2k: a.log_base2k(),
228            log_k: a.log_k(),
229        };
230
231        let min_rows: usize = res.rows().min(a.rows());
232
233        (0..res.rows()).for_each(|row_i| {
234            (0..self.cols()).for_each(|col_j| {
235                a.get_row(module, row_i, col_j, &mut tmp_row);
236                self.mul_rlwe_dft_inplace(module, &mut tmp_row, scratch1);
237                res.set_row(module, row_i, col_j, &tmp_row);
238            });
239        });
240
241        tmp_row.data.zero();
242
243        (min_rows..res.rows()).for_each(|row_i| {
244            (0..self.cols()).for_each(|col_j| {
245                res.set_row(module, row_i, col_j, &tmp_row);
246            });
247        });
248    }
249
250    fn mul_mat_rlwe_inplace<R>(&self, module: &Module<FFT64>, res: &mut R, scratch: &mut Scratch)
251    where
252        R: GetRow<FFT64> + SetRow<FFT64> + Infos,
253    {
254        let (tmp_row_data, scratch1) = scratch.tmp_vec_znx_dft(module, 2, res.size());
255
256        let mut tmp_row: RLWECtDft<&mut [u8], FFT64> = RLWECtDft::<&mut [u8], FFT64> {
257            data: tmp_row_data,
258            log_base2k: res.log_base2k(),
259            log_k: res.log_k(),
260        };
261
262        (0..res.rows()).for_each(|row_i| {
263            (0..self.cols()).for_each(|col_j| {
264                res.get_row(module, row_i, col_j, &mut tmp_row);
265                self.mul_rlwe_dft_inplace(module, &mut tmp_row, scratch1);
266                res.set_row(module, row_i, col_j, &tmp_row);
267            });
268        });
269    }
270}