arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/compressed/lwe_ct.rs
poulpy-core/src/layouts/compressed/lwe_ct.rsRaw
  1use std::fmt;
  2
  3use poulpy_hal::{
  4    api::ZnFillUniform,
  5    layouts::{
  6        Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos, ZnxView,
  7        ZnxViewMut,
  8    },
  9    source::Source,
 10};
 11
 12use crate::layouts::{Base2K, Degree, LWE, LWEInfos, LWEToMut, TorusPrecision};
 13
 14#[derive(PartialEq, Eq, Clone)]
 15pub struct LWECompressed<D: Data> {
 16    pub(crate) data: Zn<D>,
 17    pub(crate) k: TorusPrecision,
 18    pub(crate) base2k: Base2K,
 19    pub(crate) seed: [u8; 32],
 20}
 21
 22impl<D: Data> LWEInfos for LWECompressed<D> {
 23    fn base2k(&self) -> Base2K {
 24        self.base2k
 25    }
 26
 27    fn k(&self) -> TorusPrecision {
 28        self.k
 29    }
 30
 31    fn n(&self) -> Degree {
 32        Degree(self.data.n() as u32)
 33    }
 34
 35    fn size(&self) -> usize {
 36        self.data.size()
 37    }
 38}
 39
 40impl<D: DataRef> fmt::Debug for LWECompressed<D> {
 41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 42        write!(f, "{self}")
 43    }
 44}
 45
 46impl<D: DataRef> fmt::Display for LWECompressed<D> {
 47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 48        write!(
 49            f,
 50            "LWECompressed: base2k={} k={} seed={:?}: {}",
 51            self.base2k(),
 52            self.k(),
 53            self.seed,
 54            self.data
 55        )
 56    }
 57}
 58
 59impl<D: DataMut> FillUniform for LWECompressed<D> {
 60    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
 61        self.data.fill_uniform(log_bound, source);
 62    }
 63}
 64
 65pub trait LWECompressedAlloc {
 66    fn alloc_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>> {
 67        LWECompressed {
 68            data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize),
 69            k,
 70            base2k,
 71            seed: [0u8; 32],
 72        }
 73    }
 74
 75    fn alloc_lwe_compressed_from_infos<A>(&self, infos: &A) -> LWECompressed<Vec<u8>>
 76    where
 77        A: LWEInfos,
 78    {
 79        self.alloc_lwe_compressed(infos.base2k(), infos.k())
 80    }
 81
 82    fn bytes_of_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> usize {
 83        Zn::bytes_of(1, 1, k.0.div_ceil(base2k.0) as usize)
 84    }
 85
 86    fn bytes_of_lwe_compressed_from_infos<A>(&self, infos: &A) -> usize
 87    where
 88        A: LWEInfos,
 89    {
 90        self.bytes_of_lwe_compressed(infos.base2k(), infos.k())
 91    }
 92}
 93
 94impl LWECompressed<Vec<u8>> {
 95    pub fn alloc_from_infos<A, B: Backend>(module: &Module<B>, infos: &A) -> Self
 96    where
 97        A: LWEInfos,
 98        Module<B>: LWECompressedAlloc,
 99    {
100        module.alloc_lwe_compressed_from_infos(infos)
101    }
102
103    pub fn alloc<B: Backend>(module: &Module<B>, base2k: Base2K, k: TorusPrecision) -> Self
104    where
105        Module<B>: LWECompressedAlloc,
106    {
107        module.alloc_lwe_compressed(base2k, k)
108    }
109
110    pub fn bytes_of_from_infos<A, B: Backend>(module: &Module<B>, infos: &A) -> usize
111    where
112        A: LWEInfos,
113        Module<B>: LWECompressedAlloc,
114    {
115        module.bytes_of_lwe_compressed_from_infos(infos)
116    }
117
118    pub fn bytes_of<B: Backend>(module: &Module<B>, base2k: Base2K, k: TorusPrecision) -> usize
119    where
120        Module<B>: LWECompressedAlloc,
121    {
122        module.bytes_of_lwe_compressed(base2k, k)
123    }
124}
125
126use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
127
128impl<D: DataMut> ReaderFrom for LWECompressed<D> {
129    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
130        self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
131        self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
132        reader.read_exact(&mut self.seed)?;
133        self.data.read_from(reader)
134    }
135}
136
137impl<D: DataRef> WriterTo for LWECompressed<D> {
138    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
139        writer.write_u32::<LittleEndian>(self.k.into())?;
140        writer.write_u32::<LittleEndian>(self.base2k.into())?;
141        writer.write_all(&self.seed)?;
142        self.data.write_to(writer)
143    }
144}
145
146pub trait LWEDecompress
147where
148    Self: ZnFillUniform,
149{
150    fn decompress_lwe<R, O>(&self, res: &mut R, other: &O)
151    where
152        R: LWEToMut,
153        O: LWECompressedToRef,
154    {
155        let res: &mut LWE<&mut [u8]> = &mut res.to_mut();
156        let other: &LWECompressed<&[u8]> = &other.to_ref();
157
158        assert_eq!(res.lwe_layout(), other.lwe_layout());
159
160        let mut source: Source = Source::new(other.seed);
161        self.zn_fill_uniform(
162            res.n().into(),
163            other.base2k().into(),
164            &mut res.data,
165            0,
166            &mut source,
167        );
168        for i in 0..res.size() {
169            res.data.at_mut(0, i)[0] = other.data.at(0, i)[0];
170        }
171    }
172}
173
174impl<B: Backend> LWEDecompress for Module<B> where Self: ZnFillUniform {}
175
176impl<D: DataMut> LWE<D> {
177    pub fn decompress<O, B: Backend>(&mut self, module: &Module<B>, other: &O)
178    where
179        O: LWECompressedToRef,
180        Module<B>: LWEDecompress,
181    {
182        module.decompress_lwe(self, other);
183    }
184}
185
186pub trait LWECompressedToRef {
187    fn to_ref(&self) -> LWECompressed<&[u8]>;
188}
189
190impl<D: DataRef> LWECompressedToRef for LWECompressed<D> {
191    fn to_ref(&self) -> LWECompressed<&[u8]> {
192        LWECompressed {
193            k: self.k,
194            base2k: self.base2k,
195            seed: self.seed,
196            data: self.data.to_ref(),
197        }
198    }
199}
200
201pub trait LWECompressedToMut {
202    fn to_mut(&mut self) -> LWECompressed<&mut [u8]>;
203}
204
205impl<D: DataMut> LWECompressedToMut for LWECompressed<D> {
206    fn to_mut(&mut self) -> LWECompressed<&mut [u8]> {
207        LWECompressed {
208            k: self.k,
209            base2k: self.base2k,
210            seed: self.seed,
211            data: self.data.to_mut(),
212        }
213    }
214}