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