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, LWEInfos, Rank, TorusPrecision, prepared::{Prepare, PrepareAlloc, PrepareScratchSpace}, }, }; pub struct GLWESecretPrepared { pub(crate) data: SvpPPol, pub(crate) dist: Distribution, } 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) } } impl PrepareScratchSpace for GLWESecretPrepared, B> { fn prepare_scratch_space(_module: &Module, _infos: &A) -> usize { 0 } } impl PrepareAlloc, B>> for GLWESecret where Module: SvpPrepare + SvpPPolAlloc, { fn prepare_alloc(&self, module: &Module, _scratch: &mut Scratch) -> GLWESecretPrepared, B> { let mut sk_dft: GLWESecretPrepared, B> = GLWESecretPrepared::alloc(module, self); sk_dft.prepare(module, self, _scratch); sk_dft } } impl Prepare> for GLWESecretPrepared where Module: SvpPrepare, { fn prepare(&mut self, module: &Module, other: &GLWESecret, _scratch: &mut Scratch) { (0..self.rank().into()).for_each(|i| { module.svp_prepare(&mut self.data, i, &other.data, i); }); self.dist = other.dist } } 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_ref(&mut self) -> GLWESecretPrepared<&mut [u8], B>; } impl GLWESecretPreparedToMut for GLWESecretPrepared { fn to_ref(&mut self) -> GLWESecretPrepared<&mut [u8], B> { GLWESecretPrepared { dist: self.dist, data: self.data.to_mut(), } } }