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