poulpy_core/layouts/
glwe.rs

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