use poulpy_hal::{ api::{VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalizeInplace}, layouts::{Backend, DataMut, Module, Scratch, VecZnx, ZnxView, ZnxViewMut}, source::Source, }; use crate::{ ScratchTakeCore, encryption::{SIGMA, SIGMA_BOUND}, layouts::{LWE, LWEInfos, LWEPlaintext, LWEPlaintextToRef, LWESecret, LWESecretToRef, LWEToMut}, }; impl LWE { pub fn encrypt_sk( &mut self, module: &M, pt: &P, sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where P: LWEPlaintextToRef, S: LWESecretToRef, M: LWEEncryptSk, Scratch: ScratchTakeCore, { module.lwe_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch); } } pub trait LWEEncryptSk { fn lwe_encrypt_sk( &self, res: &mut R, pt: &P, sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where R: LWEToMut, P: LWEPlaintextToRef, S: LWESecretToRef, Scratch: ScratchTakeCore; } impl LWEEncryptSk for Module where Self: Sized + VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace, { fn lwe_encrypt_sk( &self, res: &mut R, pt: &P, sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) where R: LWEToMut, P: LWEPlaintextToRef, S: LWESecretToRef, Scratch: ScratchTakeCore, { let res: &mut LWE<&mut [u8]> = &mut res.to_mut(); let pt: &LWEPlaintext<&[u8]> = &pt.to_ref(); let sk: &LWESecret<&[u8]> = &sk.to_ref(); #[cfg(debug_assertions)] { assert_eq!(res.n(), sk.n()) } let base2k: usize = res.base2k().into(); let k: usize = res.k().into(); self.vec_znx_fill_uniform(base2k, &mut res.data, 0, source_xa); let mut tmp_znx: VecZnx> = VecZnx::alloc(1, 1, res.size()); let min_size: usize = res.size().min(pt.size()); (0..min_size).for_each(|i| { tmp_znx.at_mut(0, i)[0] = pt.data.at(0, i)[0] - res.data.at(0, i)[1..] .iter() .zip(sk.data.at(0, 0)) .map(|(x, y)| x * y) .sum::(); }); (min_size..res.size()).for_each(|i| { tmp_znx.at_mut(0, i)[0] -= res.data.at(0, i)[1..] .iter() .zip(sk.data.at(0, 0)) .map(|(x, y)| x * y) .sum::(); }); self.vec_znx_add_normal(base2k, &mut tmp_znx, 0, k, source_xe, SIGMA, SIGMA_BOUND); self.vec_znx_normalize_inplace(base2k, &mut tmp_znx, 0, scratch); (0..res.size()).for_each(|i| { res.data.at_mut(0, i)[0] = tmp_znx.at(0, i)[0]; }); } }