use backend::hal::{ api::{ScalarZnxAlloc, ScalarZnxAllocBytes, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, ZnxInfos, ZnxZero}, layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, SvpPPol, WriterTo}, }; use sampling::source::Source; use crate::dist::Distribution; pub trait GLWESecretFamily = SvpPrepare + SvpPPolAllocBytes + SvpPPolAlloc; #[derive(PartialEq, Eq)] pub struct GLWESecret { pub(crate) data: ScalarZnx, pub(crate) dist: Distribution, } impl GLWESecret> { pub fn alloc(module: &Module, rank: usize) -> Self where Module: ScalarZnxAlloc, { Self { data: module.scalar_znx_alloc(rank), dist: Distribution::NONE, } } pub fn bytes_of(module: &Module, rank: usize) -> usize where Module: ScalarZnxAllocBytes, { module.scalar_znx_alloc_bytes(rank) } } impl GLWESecret { pub fn n(&self) -> usize { self.data.n() } pub fn log_n(&self) -> usize { self.data.log_n() } pub fn rank(&self) -> usize { self.data.cols() } } impl GLWESecret { pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { (0..self.rank()).for_each(|i| { self.data.fill_ternary_prob(i, prob, source); }); self.dist = Distribution::TernaryProb(prob); } pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { (0..self.rank()).for_each(|i| { self.data.fill_ternary_hw(i, hw, source); }); self.dist = Distribution::TernaryFixed(hw); } pub fn fill_binary_prob(&mut self, prob: f64, source: &mut Source) { (0..self.rank()).for_each(|i| { self.data.fill_binary_prob(i, prob, source); }); self.dist = Distribution::BinaryProb(prob); } pub fn fill_binary_hw(&mut self, hw: usize, source: &mut Source) { (0..self.rank()).for_each(|i| { self.data.fill_binary_hw(i, hw, source); }); self.dist = Distribution::BinaryFixed(hw); } pub fn fill_binary_block(&mut self, block_size: usize, source: &mut Source) { (0..self.rank()).for_each(|i| { self.data.fill_binary_block(i, block_size, source); }); self.dist = Distribution::BinaryBlock(block_size); } pub fn fill_zero(&mut self) { self.data.zero(); self.dist = Distribution::ZERO; } } impl ReaderFrom for GLWESecret { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { match Distribution::read_from(reader) { Ok(dist) => self.dist = dist, Err(e) => return Err(e), } self.data.read_from(reader) } } impl WriterTo for GLWESecret { fn write_to(&self, writer: &mut W) -> std::io::Result<()> { match self.dist.write_to(writer) { Ok(()) => {} Err(e) => return Err(e), } self.data.write_to(writer) } } pub struct GLWESecretExec { pub(crate) data: SvpPPol, pub(crate) dist: Distribution, } impl GLWESecretExec, B> { pub fn alloc(module: &Module, rank: usize) -> Self where Module: GLWESecretFamily, { Self { data: module.svp_ppol_alloc(rank), dist: Distribution::NONE, } } pub fn bytes_of(module: &Module, rank: usize) -> usize where Module: GLWESecretFamily, { module.svp_ppol_alloc_bytes(rank) } } impl GLWESecretExec, B> { pub fn from(module: &Module, sk: &GLWESecret) -> Self where D: DataRef, Module: GLWESecretFamily, { let mut sk_dft: GLWESecretExec, B> = Self::alloc(module, sk.rank()); sk_dft.prepare(module, sk); sk_dft } } impl GLWESecretExec { pub fn n(&self) -> usize { self.data.n() } pub fn log_n(&self) -> usize { self.data.log_n() } pub fn rank(&self) -> usize { self.data.cols() } } impl GLWESecretExec { pub(crate) fn prepare(&mut self, module: &Module, sk: &GLWESecret) where O: DataRef, Module: GLWESecretFamily, { (0..self.rank()).for_each(|i| { module.svp_prepare(&mut self.data, i, &sk.data, i); }); self.dist = sk.dist } }