use std::fmt; use backend::hal::{ api::{FillUniform, Reset, VecZnxFillUniform, ZnxInfos, ZnxView, ZnxViewMut}, layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, VecZnx, WriterTo}, }; use sampling::source::Source; use crate::{ Decompress, GGLWEEncryptSkFamily, GLWESwitchingKeyCompressed, GLWEToLWESwitchingKey, Infos, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, 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 { 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]; }); } } #[derive(PartialEq, Eq, Clone)] pub struct GLWEToLWESwitchingKeyCompressed(pub(crate) GLWESwitchingKeyCompressed); impl fmt::Debug for GLWEToLWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) } } impl FillUniform for GLWEToLWESwitchingKeyCompressed { fn fill_uniform(&mut self, source: &mut sampling::source::Source) { self.0.fill_uniform(source); } } impl Reset for GLWEToLWESwitchingKeyCompressed { fn reset(&mut self) { self.0.reset(); } } impl fmt::Display for GLWEToLWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(GLWEToLWESwitchingKeyCompressed) {}", self.0) } } impl Infos for GLWEToLWESwitchingKeyCompressed { type Inner = MatZnx; fn inner(&self) -> &Self::Inner { &self.0.inner() } fn basek(&self) -> usize { self.0.basek() } fn k(&self) -> usize { self.0.k() } } impl GLWEToLWESwitchingKeyCompressed { pub fn digits(&self) -> usize { self.0.digits() } pub fn rank(&self) -> usize { self.0.rank() } pub fn rank_in(&self) -> usize { self.0.rank_in() } pub fn rank_out(&self) -> usize { self.0.rank_out() } } impl ReaderFrom for GLWEToLWESwitchingKeyCompressed { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { self.0.read_from(reader) } } impl WriterTo for GLWEToLWESwitchingKeyCompressed { fn write_to(&self, writer: &mut W) -> std::io::Result<()> { self.0.write_to(writer) } } impl GLWEToLWESwitchingKeyCompressed> { pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self { Self(GLWESwitchingKeyCompressed::alloc( n, basek, k, rows, 1, rank_in, 1, )) } pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank_in: usize) -> usize where Module: GGLWEEncryptSkFamily, { GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_in) } } #[derive(PartialEq, Eq, Clone)] pub struct LWEToGLWESwitchingKeyCompressed(pub(crate) GLWESwitchingKeyCompressed); impl fmt::Debug for LWEToGLWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) } } impl FillUniform for LWEToGLWESwitchingKeyCompressed { fn fill_uniform(&mut self, source: &mut sampling::source::Source) { self.0.fill_uniform(source); } } impl Reset for LWEToGLWESwitchingKeyCompressed { fn reset(&mut self) { self.0.reset(); } } impl fmt::Display for LWEToGLWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0) } } impl Infos for LWEToGLWESwitchingKeyCompressed { type Inner = MatZnx; fn inner(&self) -> &Self::Inner { &self.0.inner() } fn basek(&self) -> usize { self.0.basek() } fn k(&self) -> usize { self.0.k() } } impl LWEToGLWESwitchingKeyCompressed { pub fn digits(&self) -> usize { self.0.digits() } pub fn rank(&self) -> usize { self.0.rank() } pub fn rank_in(&self) -> usize { self.0.rank_in() } pub fn rank_out(&self) -> usize { self.0.rank_out() } } impl ReaderFrom for LWEToGLWESwitchingKeyCompressed { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { self.0.read_from(reader) } } impl WriterTo for LWEToGLWESwitchingKeyCompressed { fn write_to(&self, writer: &mut W) -> std::io::Result<()> { self.0.write_to(writer) } } impl LWEToGLWESwitchingKeyCompressed> { pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self { Self(GLWESwitchingKeyCompressed::alloc( n, basek, k, rows, 1, 1, rank_out, )) } pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize, rank_out: usize) -> usize where Module: GGLWEEncryptSkFamily, { LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank_out) } } #[derive(PartialEq, Eq, Clone)] pub struct LWESwitchingKeyCompressed(pub(crate) GLWESwitchingKeyCompressed); impl fmt::Debug for LWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) } } impl FillUniform for LWESwitchingKeyCompressed { fn fill_uniform(&mut self, source: &mut sampling::source::Source) { self.0.fill_uniform(source); } } impl Reset for LWESwitchingKeyCompressed { fn reset(&mut self) { self.0.reset(); } } impl fmt::Display for LWESwitchingKeyCompressed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(LWESwitchingKeyCompressed) {}", self.0) } } impl Infos for LWESwitchingKeyCompressed { type Inner = MatZnx; fn inner(&self) -> &Self::Inner { &self.0.inner() } fn basek(&self) -> usize { self.0.basek() } fn k(&self) -> usize { self.0.k() } } impl LWESwitchingKeyCompressed { pub fn digits(&self) -> usize { self.0.digits() } pub fn rank(&self) -> usize { self.0.rank() } pub fn rank_in(&self) -> usize { self.0.rank_in() } pub fn rank_out(&self) -> usize { self.0.rank_out() } } impl ReaderFrom for LWESwitchingKeyCompressed { fn read_from(&mut self, reader: &mut R) -> std::io::Result<()> { self.0.read_from(reader) } } impl WriterTo for LWESwitchingKeyCompressed { fn write_to(&self, writer: &mut W) -> std::io::Result<()> { self.0.write_to(writer) } } impl LWESwitchingKeyCompressed> { pub fn alloc(n: usize, basek: usize, k: usize, rows: usize) -> Self { Self(GLWESwitchingKeyCompressed::alloc( n, basek, k, rows, 1, 1, 1, )) } pub fn encrypt_sk_scratch_space(module: &Module, n: usize, basek: usize, k: usize) -> usize where Module: GGLWEEncryptSkFamily, { LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k) } }