arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/noise/ggsw_ct.rs
poulpy-core/src/noise/ggsw_ct.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxAddScalarInplace, VecZnxBigAddInplace,
  4        VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
  5        VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalizeTmpBytes,
  6        VecZnxSubInplace,
  7        ScratchTakeBasic,
  8    },
  9    layouts::{Backend, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ScratchOwned, VecZnxBig, VecZnxDft, ZnxZero},
 10    oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl},
 11};
 12
 13use crate::layouts::{GGSW, GGSWInfos, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared, GGSWToRef};
 14use crate::layouts::prepared::GLWESecretPreparedToRef;
 15use crate::decryption::GLWEDecryption;
 16
 17impl<D: DataRef> GGSW<D> {
 18    pub fn assert_noise<M, BE, DataSk, DataScalar, F>(
 19        &self,
 20        module: &M,
 21        sk_prepared: &GLWESecretPrepared<DataSk, BE>,
 22        pt_want: &ScalarZnx<DataScalar>,
 23        max_noise: F
 24    ) where
 25        DataSk: DataRef,
 26        DataScalar: DataRef,
 27        M: GGSWNoise<BE>,
 28        BE: Backend + ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>,
 29        F: Fn(usize) -> f64,
 30    {
 31        module.ggsw_assert_noise(self, sk_prepared, pt_want, max_noise);
 32    }
 33
 34    pub fn print_noise<M, BE, DataSk, DataScalar>(
 35        &self,
 36        module: &M,
 37        sk_prepared: &GLWESecretPrepared<DataSk, BE>,
 38        pt_want: &ScalarZnx<DataScalar>,
 39    ) where
 40        DataSk: DataRef,
 41        DataScalar: DataRef,
 42        M: GGSWNoise<BE>,
 43        BE: Backend + ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>,
 44    {
 45        module.ggsw_print_noise(self, sk_prepared, pt_want);
 46    }
 47}
 48
 49pub trait GGSWNoise<BE: Backend> {
 50    fn ggsw_assert_noise<R, S, P, F>(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: F)
 51    where
 52        R: GGSWToRef,
 53        S: GLWESecretPreparedToRef<BE>,
 54        P: ScalarZnxToRef,
 55        BE: ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>,
 56        F: Fn(usize) -> f64;
 57
 58    fn ggsw_print_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P)
 59    where
 60        R: GGSWToRef,
 61        S: GLWESecretPreparedToRef<BE>,
 62        P: ScalarZnxToRef,
 63        BE: ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>;
 64}
 65
 66impl<BE: Backend> GGSWNoise<BE> for Module<BE>
 67where
 68    Module<BE>: VecZnxDftBytesOf
 69        + VecZnxBigBytesOf
 70        + VecZnxDftApply<BE>
 71        + SvpApplyDftToDftInplace<BE>
 72        + VecZnxIdftApplyConsume<BE>
 73        + VecZnxBigAddInplace<BE>
 74        + VecZnxBigAddSmallInplace<BE>
 75        + VecZnxBigNormalize<BE>
 76        + VecZnxNormalizeTmpBytes
 77        + VecZnxBigAlloc<BE>
 78        + VecZnxDftAlloc<BE>
 79        + VecZnxBigNormalizeTmpBytes
 80        + VecZnxIdftApplyTmpA<BE>
 81        + VecZnxAddScalarInplace
 82        + VecZnxSubInplace
 83        + GLWEDecryption<BE>,
 84    Scratch<BE>: ScratchTakeBasic,
 85{
 86    fn ggsw_assert_noise<R, S, P, F>(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: F)
 87    where
 88        R: GGSWToRef,
 89        S: GLWESecretPreparedToRef<BE>,
 90        P: ScalarZnxToRef,
 91        BE: ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>,
 92        F: Fn(usize) -> f64,
 93    {
 94
 95        let res: &GGSW<&[u8]> = &res.to_ref();
 96        let sk_prepared: &GLWESecretPrepared<&[u8], BE> = &sk_prepared.to_ref();
 97
 98        let base2k: usize = res.base2k().into();
 99        let dsize: usize = res.dsize().into();
100
101        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(self, res);
102        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(self, res);
103        let mut pt_dft: VecZnxDft<Vec<u8>, BE> = self.vec_znx_dft_alloc(1, res.size());
104        let mut pt_big: VecZnxBig<Vec<u8>, BE> = self.vec_znx_big_alloc(1, res.size());
105
106        let mut scratch: ScratchOwned<BE> =
107            ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res) | self.vec_znx_normalize_tmp_bytes());
108
109        (0..(res.rank() + 1).into()).for_each(|col_j| {
110            (0..res.dnum().into()).for_each(|row_i| {
111                self.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0);
112
113                // mul with sk[col_j-1]
114                if col_j > 0 {
115                    self.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0);
116                    self.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1);
117                    self.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0);
118                    self.vec_znx_big_normalize(
119                        base2k,
120                        &mut pt.data,
121                        0,
122                        base2k,
123                        &pt_big,
124                        0,
125                        scratch.borrow(),
126                    );
127                }
128
129                self.glwe_decrypt(&res.at(row_i, col_j), &mut pt_have, sk_prepared, scratch.borrow());
130
131                self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0);
132
133                let std_pt: f64 = pt_have.data.std(base2k, 0).log2();
134                let noise: f64 = max_noise(col_j);
135                assert!(std_pt <= noise, "{std_pt} > {noise}");
136
137                pt.data.zero();
138            });
139        });       
140    }
141
142    fn ggsw_print_noise<R, S, P>(&self, res: &R, sk_prepared: &S, pt_want: &P)
143    where
144        R: GGSWToRef,
145        S: GLWESecretPreparedToRef<BE>,
146        P: ScalarZnxToRef,
147        BE: ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE> + ScratchOwnedBorrow<BE>,
148    {
149        let res: &GGSW<&[u8]> = &res.to_ref();
150        let sk_prepared: &GLWESecretPrepared<&[u8], BE> = &sk_prepared.to_ref();
151
152        let base2k: usize = res.base2k().into();
153        let dsize: usize = res.dsize().into();
154
155        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(self, res);
156        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(self, res);
157        let mut pt_dft: VecZnxDft<Vec<u8>, BE> = self.vec_znx_dft_alloc(1, res.size());
158        let mut pt_big: VecZnxBig<Vec<u8>, BE> = self.vec_znx_big_alloc(1, res.size());
159
160        let mut scratch: ScratchOwned<BE> =
161            ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res) | self.vec_znx_normalize_tmp_bytes());
162
163        (0..(res.rank() + 1).into()).for_each(|col_j| {
164            (0..res.dnum().into()).for_each(|row_i| {
165                self.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0);
166
167                // mul with sk[col_j-1]
168                if col_j > 0 {
169                    self.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0);
170                    self.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1);
171                    self.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0);
172                    self.vec_znx_big_normalize(
173                        base2k,
174                        &mut pt.data,
175                        0,
176                        base2k,
177                        &pt_big,
178                        0,
179                        scratch.borrow(),
180                    );
181                }
182
183                self.glwe_decrypt(&res.at(row_i, col_j), &mut pt_have, sk_prepared, scratch.borrow());
184                self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0);
185
186                let std_pt: f64 = pt_have.data.std(base2k, 0).log2();
187                println!("col: {col_j} row: {row_i}: {std_pt}");
188                pt.data.zero();
189            });
190        });
191    }   
192}