use std::fmt; use backend::hal::{ api::{FillUniform, Reset, VecZnxFillUniform, ZnxInfos, ZnxView, ZnxViewMut}, layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, WriterTo}, }; use sampling::source::Source; use crate::{Decompress, Infos, LWECiphertext, SetMetaData}; #[derive(PartialEq, Eq, Clone)] pub struct LWECiphertextCompressed { pub(crate) data: VecZnx, pub(crate) k: usize, pub(crate) basek: usize, pub(crate) seed: [u8; 32], } impl fmt::Debug for LWECiphertextCompressed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) } } impl fmt::Display for LWECiphertextCompressed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "LWECiphertextCompressed: basek={} k={} seed={:?}: {}", self.basek(), self.k(), self.seed, self.data ) } } impl Reset for LWECiphertextCompressed where VecZnx: Reset, { fn reset(&mut self) { self.data.reset(); self.basek = 0; self.k = 0; self.seed = [0u8; 32]; } } impl FillUniform for LWECiphertextCompressed where VecZnx: FillUniform, { fn fill_uniform(&mut self, source: &mut Source) { self.data.fill_uniform(source); } } impl LWECiphertextCompressed> { pub fn alloc(basek: usize, k: usize) -> Self { Self { data: VecZnx::alloc(1, 1, k.div_ceil(basek)), k: k, basek: basek, seed: [0u8; 32], } } } impl Infos for LWECiphertextCompressed where VecZnx: ZnxInfos, { type Inner = VecZnx; fn n(&self) -> usize { &self.inner().n() - 1 } fn inner(&self) -> &Self::Inner { &self.data } fn basek(&self) -> usize { self.basek } fn k(&self) -> usize { self.k } } impl SetMetaData for LWECiphertextCompressed { fn set_k(&mut self, k: usize) { self.k = k } fn set_basek(&mut self, basek: usize) { self.basek = basek } } use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; impl ReaderFrom for LWECiphertextCompressed { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = reader.read_u64::()? as usize; self.basek = reader.read_u64::()? as usize; reader.read(&mut self.seed)?; self.data.read_from(reader) } } impl WriterTo for LWECiphertextCompressed { fn write_to(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::(self.k as u64)?; writer.write_u64::(self.basek as u64)?; writer.write_all(&self.seed)?; self.data.write_to(writer) } } impl Decompress> for LWECiphertext { fn decompress(&mut self, module: &Module, other: &LWECiphertextCompressed) where Module: VecZnxFillUniform, { let mut source = Source::new(other.seed); module.vec_znx_fill_uniform(other.basek(), &mut self.data, 0, other.k(), &mut source); (0..self.size()).for_each(|i| { self.data.at_mut(0, i)[0] = other.data.at(0, i)[0]; }); } }