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