arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/rlwe/src/elem_rgsw.rs
rlwe/src/elem_rgsw.rsRaw
  1use base2k::{
  2    Backend, FFT64, MatZnxDft, MatZnxDftAlloc, MatZnxDftOps, MatZnxDftToMut, MatZnxDftToRef, Module, ScalarZnx, ScalarZnxDft,
  3    ScalarZnxDftToRef, ScalarZnxToRef, Scratch, VecZnxAlloc, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxOps,
  4    ZnxZero,
  5};
  6use sampling::source::Source;
  7
  8use crate::{
  9    elem::Infos,
 10    elem_rlwe::{RLWECt, RLWECtDft, RLWEPt, encrypt_rlwe_sk},
 11    keys::SecretKeyDft,
 12    utils::derive_size,
 13};
 14
 15pub struct RGSWCt<C, B: Backend> {
 16    pub data: MatZnxDft<C, B>,
 17    pub log_base2k: usize,
 18    pub log_k: usize,
 19}
 20
 21impl<B: Backend> RGSWCt<Vec<u8>, B> {
 22    pub fn new(module: &Module<B>, log_base2k: usize, log_k: usize, rows: usize) -> Self {
 23        Self {
 24            data: module.new_mat_znx_dft(rows, 2, 2, derive_size(log_base2k, log_k)),
 25            log_base2k: log_base2k,
 26            log_k: log_k,
 27        }
 28    }
 29}
 30
 31impl<T, B: Backend> Infos for RGSWCt<T, B> {
 32    type Inner = MatZnxDft<T, B>;
 33
 34    fn inner(&self) -> &Self::Inner {
 35        &self.data
 36    }
 37
 38    fn log_base2k(&self) -> usize {
 39        self.log_base2k
 40    }
 41
 42    fn log_k(&self) -> usize {
 43        self.log_k
 44    }
 45}
 46
 47impl<C, B: Backend> MatZnxDftToMut<B> for RGSWCt<C, B>
 48where
 49    MatZnxDft<C, B>: MatZnxDftToMut<B>,
 50{
 51    fn to_mut(&mut self) -> MatZnxDft<&mut [u8], B> {
 52        self.data.to_mut()
 53    }
 54}
 55
 56impl<C, B: Backend> MatZnxDftToRef<B> for RGSWCt<C, B>
 57where
 58    MatZnxDft<C, B>: MatZnxDftToRef<B>,
 59{
 60    fn to_ref(&self) -> MatZnxDft<&[u8], B> {
 61        self.data.to_ref()
 62    }
 63}
 64
 65impl RGSWCt<Vec<u8>, FFT64> {
 66    pub fn encrypt_sk_scratch_space(module: &Module<FFT64>, size: usize) -> usize {
 67        RLWECt::encrypt_sk_scratch_space(module, size)
 68            + module.bytes_of_vec_znx(2, size)
 69            + module.bytes_of_vec_znx(1, size)
 70            + module.bytes_of_vec_znx_dft(2, size)
 71    }
 72}
 73
 74impl<C> RGSWCt<C, FFT64>
 75where
 76    MatZnxDft<C, FFT64>: MatZnxDftToRef<FFT64>,
 77{
 78    pub fn get_row(&self, module: &Module<FFT64>, row_i: usize, col_j: usize, res: &mut RLWECtDft<C, FFT64>)
 79    where
 80        VecZnxDft<C, FFT64>: VecZnxDftToMut<FFT64>,
 81    {
 82        module.vmp_extract_row(res, self, row_i, col_j);
 83    }
 84}
 85
 86pub fn encrypt_rgsw_sk<C, P, S>(
 87    module: &Module<FFT64>,
 88    ct: &mut RGSWCt<C, FFT64>,
 89    pt: &ScalarZnx<P>,
 90    sk_dft: &SecretKeyDft<S, FFT64>,
 91    source_xa: &mut Source,
 92    source_xe: &mut Source,
 93    sigma: f64,
 94    bound: f64,
 95    scratch: &mut Scratch,
 96) where
 97    MatZnxDft<C, FFT64>: MatZnxDftToMut<FFT64>,
 98    ScalarZnx<P>: ScalarZnxToRef,
 99    ScalarZnxDft<S, FFT64>: ScalarZnxDftToRef<FFT64>,
100{
101    let size: usize = ct.size();
102    let log_base2k: usize = ct.log_base2k();
103
104    let (tmp_znx_pt, scratch_1) = scratch.tmp_vec_znx(module, 1, size);
105    let (tmp_znx_ct, scrach_2) = scratch_1.tmp_vec_znx(module, 2, size);
106
107    let mut vec_znx_pt: RLWEPt<&mut [u8]> = RLWEPt {
108        data: tmp_znx_pt,
109        log_base2k: log_base2k,
110        log_k: ct.log_k(),
111    };
112
113    let mut vec_znx_ct: RLWECt<&mut [u8]> = RLWECt {
114        data: tmp_znx_ct,
115        log_base2k: log_base2k,
116        log_k: ct.log_k(),
117    };
118
119    (0..ct.rows()).for_each(|row_j| {
120        // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
121        module.vec_znx_add_scalar_inplace(&mut vec_znx_pt, 0, row_j, pt, 0);
122        module.vec_znx_normalize_inplace(log_base2k, &mut vec_znx_pt, 0, scrach_2);
123
124        (0..ct.cols()).for_each(|col_i| {
125            // rlwe encrypt of vec_znx_pt into vec_znx_ct
126            encrypt_rlwe_sk(
127                module,
128                &mut vec_znx_ct,
129                Some((&vec_znx_pt, col_i)),
130                sk_dft,
131                source_xa,
132                source_xe,
133                sigma,
134                bound,
135                scrach_2,
136            );
137
138            // Switch vec_znx_ct into DFT domain
139            {
140                let (mut vec_znx_dft_ct, _) = scrach_2.tmp_vec_znx_dft(module, 2, size);
141                module.vec_znx_dft(&mut vec_znx_dft_ct, 0, &vec_znx_ct, 0);
142                module.vec_znx_dft(&mut vec_znx_dft_ct, 1, &vec_znx_ct, 1);
143                module.vmp_prepare_row(ct, row_j, col_i, &vec_znx_dft_ct);
144            }
145        });
146
147        vec_znx_pt.data.zero(); // zeroes for next iteration
148    });
149}
150
151impl<C> RGSWCt<C, FFT64> {
152    pub fn encrypt_sk<P, S>(
153        &mut self,
154        module: &Module<FFT64>,
155        pt: &ScalarZnx<P>,
156        sk_dft: &SecretKeyDft<S, FFT64>,
157        source_xa: &mut Source,
158        source_xe: &mut Source,
159        sigma: f64,
160        bound: f64,
161        scratch: &mut Scratch,
162    ) where
163        MatZnxDft<C, FFT64>: MatZnxDftToMut<FFT64>,
164        ScalarZnx<P>: ScalarZnxToRef,
165        ScalarZnxDft<S, FFT64>: ScalarZnxDftToRef<FFT64>,
166    {
167        encrypt_rgsw_sk(
168            module, self, pt, sk_dft, source_xa, source_xe, sigma, bound, scratch,
169        )
170    }
171}