poulpy/poulpy-core/src/layouts/lwe_ksk.rs
poulpy-core/src/layouts/lwe_ksk.rsRaw
1use std::fmt;
2
3use poulpy_hal::{
4 layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
5 source::Source,
6};
7
8use crate::layouts::{
9 Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
10 GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
11};
12
13#[derive(PartialEq, Eq, Copy, Clone, Debug)]
14pub struct LWESwitchingKeyLayout {
15 pub n: RingDegree,
16 pub base2k: Base2K,
17 pub k: TorusPrecision,
18 pub dnum: Dnum,
19}
20
21impl LWEInfos for LWESwitchingKeyLayout {
22 fn n(&self) -> RingDegree {
23 self.n
24 }
25
26 fn base2k(&self) -> Base2K {
27 self.base2k
28 }
29
30 fn k(&self) -> TorusPrecision {
31 self.k
32 }
33}
34
35impl GLWEInfos for LWESwitchingKeyLayout {
36 fn rank(&self) -> Rank {
37 self.rank_out()
38 }
39}
40
41impl GGLWEInfos for LWESwitchingKeyLayout {
42 fn rank_in(&self) -> Rank {
43 Rank(1)
44 }
45
46 fn dsize(&self) -> Dsize {
47 Dsize(1)
48 }
49
50 fn rank_out(&self) -> Rank {
51 Rank(1)
52 }
53
54 fn dnum(&self) -> Dnum {
55 self.dnum
56 }
57}
58
59#[derive(PartialEq, Eq, Clone)]
60pub struct LWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
61
62impl<D: Data> LWEInfos for LWESwitchingKey<D> {
63 fn base2k(&self) -> Base2K {
64 self.0.base2k()
65 }
66
67 fn k(&self) -> TorusPrecision {
68 self.0.k()
69 }
70
71 fn n(&self) -> RingDegree {
72 self.0.n()
73 }
74
75 fn size(&self) -> usize {
76 self.0.size()
77 }
78}
79
80impl<D: Data> GLWEInfos for LWESwitchingKey<D> {
81 fn rank(&self) -> Rank {
82 self.rank_out()
83 }
84}
85
86impl<D: Data> GGLWEInfos for LWESwitchingKey<D> {
87 fn dsize(&self) -> Dsize {
88 self.0.dsize()
89 }
90
91 fn rank_in(&self) -> Rank {
92 self.0.rank_in()
93 }
94
95 fn rank_out(&self) -> Rank {
96 self.0.rank_out()
97 }
98
99 fn dnum(&self) -> Dnum {
100 self.0.dnum()
101 }
102}
103
104pub trait LWESwitchingKeyAlloc
105where
106 Self: GLWESwitchingKeyAlloc,
107{
108 fn alloc_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> LWESwitchingKey<Vec<u8>> {
109 LWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)))
110 }
111
112 fn alloc_lwe_switching_key_from_infos<A>(&self, infos: &A) -> LWESwitchingKey<Vec<u8>>
113 where
114 A: GGLWEInfos,
115 {
116 assert_eq!(
117 infos.dsize().0,
118 1,
119 "dsize > 1 is not supported for LWESwitchingKey"
120 );
121 assert_eq!(
122 infos.rank_in().0,
123 1,
124 "rank_in > 1 is not supported for LWESwitchingKey"
125 );
126 assert_eq!(
127 infos.rank_out().0,
128 1,
129 "rank_out > 1 is not supported for LWESwitchingKey"
130 );
131 self.alloc_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum())
132 }
133
134 fn bytes_of_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
135 self.bytes_of_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
136 }
137
138 fn bytes_of_lwe_switching_key_from_infos<A>(&self, infos: &A) -> usize
139 where
140 A: GGLWEInfos,
141 {
142 assert_eq!(
143 infos.dsize().0,
144 1,
145 "dsize > 1 is not supported for LWESwitchingKey"
146 );
147 assert_eq!(
148 infos.rank_in().0,
149 1,
150 "rank_in > 1 is not supported for LWESwitchingKey"
151 );
152 assert_eq!(
153 infos.rank_out().0,
154 1,
155 "rank_out > 1 is not supported for LWESwitchingKey"
156 );
157 self.bytes_of_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum())
158 }
159}
160
161impl<B: Backend> LWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
162
163impl LWESwitchingKey<Vec<u8>> {
164 pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
165 where
166 A: GGLWEInfos,
167 M: LWESwitchingKeyAlloc,
168 {
169 module.alloc_lwe_switching_key_from_infos(infos)
170 }
171
172 pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
173 where
174 M: LWESwitchingKeyAlloc,
175 {
176 module.alloc_lwe_switching_key(base2k, k, dnum)
177 }
178
179 pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
180 where
181 A: GGLWEInfos,
182 M: LWESwitchingKeyAlloc,
183 {
184 module.bytes_of_glwe_switching_key_from_infos(infos)
185 }
186
187 pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
188 where
189 M: LWESwitchingKeyAlloc,
190 {
191 module.bytes_of_lwe_switching_key(base2k, k, dnum)
192 }
193}
194
195impl<D: DataRef> fmt::Debug for LWESwitchingKey<D> {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 write!(f, "{self}")
198 }
199}
200
201impl<D: DataMut> FillUniform for LWESwitchingKey<D> {
202 fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
203 self.0.fill_uniform(log_bound, source);
204 }
205}
206
207impl<D: DataRef> fmt::Display for LWESwitchingKey<D> {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 write!(f, "(LWESwitchingKey) {}", self.0)
210 }
211}
212
213impl<D: DataMut> ReaderFrom for LWESwitchingKey<D> {
214 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
215 self.0.read_from(reader)
216 }
217}
218
219impl<D: DataRef> WriterTo for LWESwitchingKey<D> {
220 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
221 self.0.write_to(writer)
222 }
223}
224
225pub trait LWESwitchingKeyToRef {
226 fn to_ref(&self) -> LWESwitchingKey<&[u8]>;
227}
228
229impl<D: DataRef> LWESwitchingKeyToRef for LWESwitchingKey<D>
230where
231 GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
232{
233 fn to_ref(&self) -> LWESwitchingKey<&[u8]> {
234 LWESwitchingKey(self.0.to_ref())
235 }
236}
237
238pub trait LWESwitchingKeyToMut {
239 fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]>;
240}
241
242impl<D: DataMut> LWESwitchingKeyToMut for LWESwitchingKey<D>
243where
244 GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
245{
246 fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]> {
247 LWESwitchingKey(self.0.to_mut())
248 }
249}