use poulpy_hal::{ api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare}, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, SvpPPol, SvpPPolToMut, SvpPPolToRef, ZnxInfos}, }; use crate::{ dist::Distribution, layouts::{ Base2K, Degree, GLWEInfos, GLWESecret, GLWESecretToMut, GLWESecretToRef, LWEInfos, Rank, TorusPrecision, prepared::SetDist, }, }; pub struct GLWESecretPrepared { pub(crate) data: SvpPPol, pub(crate) dist: Distribution, } impl SetDist for GLWESecretPrepared { fn set_dist(&mut self, dist: Distribution) { self.dist = dist } } impl LWEInfos for GLWESecretPrepared { fn base2k(&self) -> Base2K { Base2K(0) } fn k(&self) -> TorusPrecision { TorusPrecision(0) } fn n(&self) -> Degree { Degree(self.data.n() as u32) } fn size(&self) -> usize { self.data.size() } } impl GLWEInfos for GLWESecretPrepared { fn rank(&self) -> Rank { Rank(self.data.cols() as u32) } } impl GLWESecretPrepared, B> { pub fn alloc(module: &Module, infos: &A) -> Self where A: GLWEInfos, Module: SvpPPolAlloc, { assert_eq!(module.n() as u32, infos.n()); Self::alloc_with(module, infos.rank()) } pub fn alloc_with(module: &Module, rank: Rank) -> Self where Module: SvpPPolAlloc, { Self { data: module.svp_ppol_alloc(rank.into()), dist: Distribution::NONE, } } pub fn alloc_bytes(module: &Module, infos: &A) -> usize where A: GLWEInfos, Module: SvpPPolAllocBytes, { assert_eq!(module.n() as u32, infos.n()); Self::alloc_bytes_with(module, infos.rank()) } pub fn alloc_bytes_with(module: &Module, rank: Rank) -> usize where Module: SvpPPolAllocBytes, { module.svp_ppol_alloc_bytes(rank.into()) } } impl GLWESecretPrepared { pub fn n(&self) -> Degree { Degree(self.data.n() as u32) } pub fn rank(&self) -> Rank { Rank(self.data.cols() as u32) } } pub trait GLWESecretPrepareTmpBytes { fn glwe_secret_prepare_tmp_bytes(&self, infos: &A) where A: GLWEInfos; } impl GLWESecretPrepareTmpBytes for Module { fn glwe_secret_prepare_tmp_bytes(&self, infos: &A) where A: GLWEInfos, { 0 } } impl GLWESecretPrepared, B> where Module: GLWESecretPrepareTmpBytes, { fn prepare_tmp_bytes(&self, module: &Module, infos: &A) -> usize where A: GLWEInfos, { 0 } } pub trait GLWESecretPrepare { fn glwe_secret_prepare(&self, res: &mut R, other: &O, scratch: &mut Scratch) where R: GLWESecretPreparedToMut + SetDist, O: GLWESecretToRef; } impl GLWESecretPrepare for Module where Module: SvpPrepare, { fn glwe_secret_prepare(&self, res: &mut R, other: &O, scratch: &mut Scratch) where R: GLWESecretPreparedToMut + SetDist, O: GLWESecretToRef, { { let res: GLWESecretPrepared<&mut [u8], _> = res.to_mut(); let other: GLWESecret<&[u8]> = other.to_ref(); for i in 0..self.rank().into() { self.svp_prepare(&mut res.data, i, &other.data, i); } } res.set_dist(other.dist); } } pub trait GLWESecretPrepareAlloc { fn glwe_secret_prepare_alloc(&self, other: &O, scratch: &mut Scratch) where O: GLWESecretToMut; } impl GLWESecretPrepareAlloc for Module where Module: GLWESecretPrepare, { fn glwe_secret_prepare_alloc(&self, other: &O, scratch: &mut Scratch) where O: GLWESecretToMut, { let mut ct_prep: GLWESecretPrepared, B> = GLWESecretPrepared::alloc(self, self); self.glwe_secret_prepare(&mut ct_prep, other, scratch); ct_prep } } pub trait GLWESecretPreparedToRef { fn to_ref(&self) -> GLWESecretPrepared<&[u8], B>; } impl GLWESecretPreparedToRef for GLWESecretPrepared { fn to_ref(&self) -> GLWESecretPrepared<&[u8], B> { GLWESecretPrepared { data: self.data.to_ref(), dist: self.dist, } } } pub trait GLWESecretPreparedToMut { fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B>; } impl GLWESecretPreparedToMut for GLWESecretPrepared { fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B> { GLWESecretPrepared { dist: self.dist, data: self.data.to_mut(), } } }