use poulpy_hal::{ api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalizeInplace, VecZnxSubInplace}, layouts::{Backend, DataRef, Module, Scratch, ScratchOwned, Stats}, }; use crate::{ ScratchTakeCore, decryption::GLWEDecrypt, layouts::{GLWE, GLWEPlaintext, GLWEPlaintextToRef, GLWEToRef, LWEInfos, prepared::GLWESecretPreparedToRef}, }; impl GLWE { pub fn noise(&self, module: &M, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> Stats where M: GLWENoise, S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef, { module.glwe_noise(self, sk_prepared, pt_want, scratch) } pub fn assert_noise(&self, module: &M, sk_prepared: &S, pt_want: &P, max_noise: f64) where S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef, M: GLWENoise, { module.glwe_assert_noise(self, sk_prepared, pt_want, max_noise); } } pub trait GLWENoise { fn glwe_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> Stats where R: GLWEToRef, S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef; fn glwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) where R: GLWEToRef, S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef; } impl GLWENoise for Module where Module: GLWEDecrypt + VecZnxSubInplace + VecZnxNormalizeInplace, ScratchOwned: ScratchOwnedAlloc + ScratchOwnedBorrow, Scratch: ScratchTakeCore, { fn glwe_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> Stats where R: GLWEToRef, S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef, { let res_ref: &GLWE<&[u8]> = &res.to_ref(); let pt_want: &GLWEPlaintext<&[u8]> = &pt_want.to_ref(); let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(res_ref); self.glwe_decrypt(res, &mut pt_have, sk_prepared, scratch); self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0); self.vec_znx_normalize_inplace(res_ref.base2k().into(), &mut pt_have.data, 0, scratch); pt_have.data.stats(res_ref.base2k().into(), 0) } fn glwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) where R: GLWEToRef, S: GLWESecretPreparedToRef, P: GLWEPlaintextToRef, { let res: &GLWE<&[u8]> = &res.to_ref(); let mut scratch: ScratchOwned = ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res)); let noise_have: f64 = self .glwe_noise(res, sk_prepared, pt_want, scratch.borrow()) .std() .log2(); assert!(noise_have <= max_noise, "{noise_have} {max_noise}"); } }