arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/rgsw.rs
core/src/rgsw.rsRaw
  1use base2k::{
  2    Backend, FFT64, MatZnxDft, MatZnxDftAlloc, MatZnxDftOps, MatZnxDftScratch, MatZnxDftToMut, MatZnxDftToRef, Module, ScalarZnx,
  3    ScalarZnxDft, ScalarZnxDftToRef, ScalarZnxToRef, Scratch, VecZnx, VecZnxAlloc, VecZnxBig, VecZnxBigOps, VecZnxBigScratch,
  4    VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxDftToRef, VecZnxOps, VecZnxToMut, VecZnxToRef, ZnxInfos,
  5    ZnxZero,
  6};
  7use sampling::source::Source;
  8
  9use crate::{
 10    elem::{GetRow, Infos, MatZnxDftProducts, SetRow},
 11    grlwe::GRLWECt,
 12    keys::SecretKeyDft,
 13    rlwe::{RLWECt, RLWECtDft, RLWEPt, encrypt_rlwe_sk},
 14    utils::derive_size,
 15};
 16
 17pub struct RGSWCt<C, B: Backend> {
 18    pub data: MatZnxDft<C, B>,
 19    pub log_base2k: usize,
 20    pub log_k: usize,
 21}
 22
 23impl<B: Backend> RGSWCt<Vec<u8>, B> {
 24    pub fn new(module: &Module<B>, log_base2k: usize, log_k: usize, rows: usize) -> Self {
 25        Self {
 26            data: module.new_mat_znx_dft(rows, 2, 2, derive_size(log_base2k, log_k)),
 27            log_base2k: log_base2k,
 28            log_k: log_k,
 29        }
 30    }
 31}
 32
 33impl<T, B: Backend> Infos for RGSWCt<T, B> {
 34    type Inner = MatZnxDft<T, B>;
 35
 36    fn inner(&self) -> &Self::Inner {
 37        &self.data
 38    }
 39
 40    fn log_base2k(&self) -> usize {
 41        self.log_base2k
 42    }
 43
 44    fn log_k(&self) -> usize {
 45        self.log_k
 46    }
 47}
 48
 49impl<C, B: Backend> MatZnxDftToMut<B> for RGSWCt<C, B>
 50where
 51    MatZnxDft<C, B>: MatZnxDftToMut<B>,
 52{
 53    fn to_mut(&mut self) -> MatZnxDft<&mut [u8], B> {
 54        self.data.to_mut()
 55    }
 56}
 57
 58impl<C, B: Backend> MatZnxDftToRef<B> for RGSWCt<C, B>
 59where
 60    MatZnxDft<C, B>: MatZnxDftToRef<B>,
 61{
 62    fn to_ref(&self) -> MatZnxDft<&[u8], B> {
 63        self.data.to_ref()
 64    }
 65}
 66
 67impl RGSWCt<Vec<u8>, FFT64> {
 68    pub fn encrypt_sk_scratch_space(module: &Module<FFT64>, size: usize) -> usize {
 69        RLWECt::encrypt_sk_scratch_space(module, size)
 70            + module.bytes_of_vec_znx(2, size)
 71            + module.bytes_of_vec_znx(1, size)
 72            + module.bytes_of_vec_znx_dft(2, size)
 73    }
 74
 75    pub fn mul_rlwe_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, rgsw_size: usize) -> usize {
 76        module.bytes_of_vec_znx_dft(2, rgsw_size)
 77            + ((module.bytes_of_vec_znx_dft(2, a_size) + module.vmp_apply_tmp_bytes(res_size, a_size, a_size, 2, 2, rgsw_size))
 78                | module.vec_znx_big_normalize_tmp_bytes())
 79    }
 80
 81    pub fn mul_rlwe_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, rgsw_size: usize) -> usize {
 82        Self::mul_rlwe_scratch_space(module, res_size, res_size, rgsw_size)
 83    }
 84
 85    pub fn mul_rlwe_dft_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize {
 86        (Self::mul_rlwe_scratch_space(module, res_size, a_size, grlwe_size) | module.vec_znx_idft_tmp_bytes())
 87            + module.bytes_of_vec_znx(2, a_size)
 88            + module.bytes_of_vec_znx(2, res_size)
 89    }
 90
 91    pub fn mul_rlwe_dft_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, grlwe_size: usize) -> usize {
 92        (Self::mul_rlwe_inplace_scratch_space(module, res_size, grlwe_size) | module.vec_znx_idft_tmp_bytes())
 93            + module.bytes_of_vec_znx(2, res_size)
 94    }
 95
 96    pub fn mul_grlwe_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize {
 97        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, grlwe_size) + module.bytes_of_vec_znx_dft(2, a_size)
 98    }
 99
100    pub fn mul_grlwe_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize {
101        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, grlwe_size) + module.bytes_of_vec_znx_dft(2, a_size)
102    }
103
104    pub fn mul_rgsw_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize {
105        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, grlwe_size) + module.bytes_of_vec_znx_dft(2, a_size)
106    }
107
108    pub fn mul_rgsw_inplace_scratch_space(module: &Module<FFT64>, res_size: usize, a_size: usize, grlwe_size: usize) -> usize {
109        Self::mul_rlwe_dft_inplace_scratch_space(module, res_size, grlwe_size) + module.bytes_of_vec_znx_dft(2, a_size)
110    }
111}
112
113pub fn encrypt_rgsw_sk<C, P, S>(
114    module: &Module<FFT64>,
115    ct: &mut RGSWCt<C, FFT64>,
116    pt: &ScalarZnx<P>,
117    sk_dft: &SecretKeyDft<S, FFT64>,
118    source_xa: &mut Source,
119    source_xe: &mut Source,
120    sigma: f64,
121    bound: f64,
122    scratch: &mut Scratch,
123) where
124    MatZnxDft<C, FFT64>: MatZnxDftToMut<FFT64>,
125    ScalarZnx<P>: ScalarZnxToRef,
126    ScalarZnxDft<S, FFT64>: ScalarZnxDftToRef<FFT64>,
127{
128    let size: usize = ct.size();
129    let log_base2k: usize = ct.log_base2k();
130
131    let (tmp_znx_pt, scratch_1) = scratch.tmp_vec_znx(module, 1, size);
132    let (tmp_znx_ct, scrach_2) = scratch_1.tmp_vec_znx(module, 2, size);
133
134    let mut vec_znx_pt: RLWEPt<&mut [u8]> = RLWEPt {
135        data: tmp_znx_pt,
136        log_base2k: log_base2k,
137        log_k: ct.log_k(),
138    };
139
140    let mut vec_znx_ct: RLWECt<&mut [u8]> = RLWECt {
141        data: tmp_znx_ct,
142        log_base2k: log_base2k,
143        log_k: ct.log_k(),
144    };
145
146    (0..ct.rows()).for_each(|row_j| {
147        // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
148        module.vec_znx_add_scalar_inplace(&mut vec_znx_pt, 0, row_j, pt, 0);
149        module.vec_znx_normalize_inplace(log_base2k, &mut vec_znx_pt, 0, scrach_2);
150
151        (0..ct.cols()).for_each(|col_i| {
152            // rlwe encrypt of vec_znx_pt into vec_znx_ct
153            encrypt_rlwe_sk(
154                module,
155                &mut vec_znx_ct,
156                Some((&vec_znx_pt, col_i)),
157                sk_dft,
158                source_xa,
159                source_xe,
160                sigma,
161                bound,
162                scrach_2,
163            );
164
165            // Switch vec_znx_ct into DFT domain
166            {
167                let (mut vec_znx_dft_ct, _) = scrach_2.tmp_vec_znx_dft(module, 2, size);
168                module.vec_znx_dft(&mut vec_znx_dft_ct, 0, &vec_znx_ct, 0);
169                module.vec_znx_dft(&mut vec_znx_dft_ct, 1, &vec_znx_ct, 1);
170                module.vmp_prepare_row(ct, row_j, col_i, &vec_znx_dft_ct);
171            }
172        });
173
174        vec_znx_pt.data.zero(); // zeroes for next iteration
175    });
176}
177
178impl<C> RGSWCt<C, FFT64> {
179    pub fn encrypt_sk<P, S>(
180        &mut self,
181        module: &Module<FFT64>,
182        pt: &ScalarZnx<P>,
183        sk_dft: &SecretKeyDft<S, FFT64>,
184        source_xa: &mut Source,
185        source_xe: &mut Source,
186        sigma: f64,
187        bound: f64,
188        scratch: &mut Scratch,
189    ) where
190        MatZnxDft<C, FFT64>: MatZnxDftToMut<FFT64>,
191        ScalarZnx<P>: ScalarZnxToRef,
192        ScalarZnxDft<S, FFT64>: ScalarZnxDftToRef<FFT64>,
193    {
194        encrypt_rgsw_sk(
195            module, self, pt, sk_dft, source_xa, source_xe, sigma, bound, scratch,
196        )
197    }
198
199    pub fn mul_rlwe<R, A>(&self, module: &Module<FFT64>, res: &mut RLWECt<R>, a: &RLWECt<A>, scratch: &mut Scratch)
200    where
201        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64>,
202        VecZnx<R>: VecZnxToMut,
203        VecZnx<A>: VecZnxToRef,
204    {
205        MatZnxDftProducts::mul_rlwe(self, module, res, a, scratch);
206    }
207
208    pub fn mul_rlwe_inplace<R>(&self, module: &Module<FFT64>, res: &mut RLWECt<R>, scratch: &mut Scratch)
209    where
210        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
211        VecZnx<R>: VecZnxToMut + VecZnxToRef,
212    {
213        MatZnxDftProducts::mul_rlwe_inplace(self, module, res, scratch);
214    }
215
216    pub fn mul_rlwe_dft<R, A>(
217        &self,
218        module: &Module<FFT64>,
219        res: &mut RLWECtDft<R, FFT64>,
220        a: &RLWECtDft<A, FFT64>,
221        scratch: &mut Scratch,
222    ) where
223        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
224        VecZnxDft<R, FFT64>: VecZnxDftToMut<FFT64> + VecZnxDftToRef<FFT64> + ZnxInfos,
225        VecZnxDft<A, FFT64>: VecZnxDftToRef<FFT64> + ZnxInfos,
226    {
227        MatZnxDftProducts::mul_rlwe_dft(self, module, res, a, scratch);
228    }
229
230    pub fn mul_rlwe_dft_inplace<R>(&self, module: &Module<FFT64>, res: &mut RLWECtDft<R, FFT64>, scratch: &mut Scratch)
231    where
232        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
233        VecZnxDft<R, FFT64>: VecZnxDftToRef<FFT64> + VecZnxDftToMut<FFT64>,
234    {
235        MatZnxDftProducts::mul_rlwe_dft_inplace(self, module, res, scratch);
236    }
237
238    pub fn mul_grlwe<R, A>(
239        &self,
240        module: &Module<FFT64>,
241        res: &mut GRLWECt<R, FFT64>,
242        a: &GRLWECt<A, FFT64>,
243        scratch: &mut Scratch,
244    ) where
245        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
246        MatZnxDft<R, FFT64>: MatZnxDftToMut<FFT64> + MatZnxDftToRef<FFT64> + ZnxInfos,
247        MatZnxDft<A, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
248    {
249        MatZnxDftProducts::mul_grlwe(self, module, res, a, scratch);
250    }
251
252    pub fn mul_grlwe_inplace<R>(&self, module: &Module<FFT64>, res: &mut R, scratch: &mut Scratch)
253    where
254        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
255        R: GetRow<FFT64> + SetRow<FFT64> + Infos,
256    {
257        MatZnxDftProducts::mul_grlwe_inplace(self, module, res, scratch);
258    }
259}
260
261impl<C> GetRow<FFT64> for RGSWCt<C, FFT64>
262where
263    MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64>,
264{
265    fn get_row<R>(&self, module: &Module<FFT64>, row_i: usize, col_j: usize, res: &mut RLWECtDft<R, FFT64>)
266    where
267        VecZnxDft<R, FFT64>: VecZnxDftToMut<FFT64>,
268    {
269        module.vmp_extract_row(res, self, row_i, col_j);
270    }
271}
272
273impl<C> SetRow<FFT64> for RGSWCt<C, FFT64>
274where
275    MatZnxDft<C, FFT64>: MatZnxDftToMut<FFT64>,
276{
277    fn set_row<R>(&mut self, module: &Module<FFT64>, row_i: usize, col_j: usize, a: &RLWECtDft<R, FFT64>)
278    where
279        VecZnxDft<R, FFT64>: VecZnxDftToRef<FFT64>,
280    {
281        module.vmp_prepare_row(self, row_i, col_j, a);
282    }
283}
284
285impl<C> MatZnxDftProducts<RGSWCt<C, FFT64>, C> for RGSWCt<C, FFT64>
286where
287    MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64> + ZnxInfos,
288{
289    fn mul_rlwe<R, A>(&self, module: &Module<FFT64>, res: &mut RLWECt<R>, a: &RLWECt<A>, scratch: &mut Scratch)
290    where
291        MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64>,
292        VecZnx<R>: VecZnxToMut,
293        VecZnx<A>: VecZnxToRef,
294    {
295        let log_base2k: usize = self.log_base2k();
296
297        #[cfg(debug_assertions)]
298        {
299            assert_eq!(res.log_base2k(), log_base2k);
300            assert_eq!(a.log_base2k(), log_base2k);
301            assert_eq!(self.n(), module.n());
302            assert_eq!(res.n(), module.n());
303            assert_eq!(a.n(), module.n());
304        }
305
306        let (mut res_dft, scratch1) = scratch.tmp_vec_znx_dft(module, 2, self.size()); // Todo optimise
307
308        {
309            let (mut a_dft, scratch2) = scratch1.tmp_vec_znx_dft(module, 2, a.size());
310            module.vec_znx_dft(&mut a_dft, 0, a, 0);
311            module.vec_znx_dft(&mut a_dft, 1, a, 1);
312            module.vmp_apply(&mut res_dft, &a_dft, self, scratch2);
313        }
314
315        let res_big: VecZnxBig<&mut [u8], FFT64> = module.vec_znx_idft_consume(res_dft);
316
317        module.vec_znx_big_normalize(log_base2k, res, 0, &res_big, 0, scratch1);
318        module.vec_znx_big_normalize(log_base2k, res, 1, &res_big, 1, scratch1);
319    }
320}