poulpy/poulpy-schemes/src/bin_fhe/blind_rotation/layouts/key.rs
poulpy-schemes/src/bin_fhe/blind_rotation/layouts/key.rsRaw
1use poulpy_hal::{
2 layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
3 source::Source,
4};
5
6use std::{fmt, marker::PhantomData};
7
8use poulpy_core::{
9 Distribution,
10 layouts::{Base2K, Degree, Dnum, Dsize, GGSW, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision},
11};
12
13use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
14
15use crate::bin_fhe::blind_rotation::BlindRotationAlgo;
16
17#[derive(PartialEq, Eq, Copy, Clone, Debug)]
18pub struct BlindRotationKeyLayout {
19 pub n_glwe: Degree,
20 pub n_lwe: Degree,
21 pub base2k: Base2K,
22 pub k: TorusPrecision,
23 pub dnum: Dnum,
24 pub rank: Rank,
25}
26
27impl BlindRotationKeyInfos for BlindRotationKeyLayout {
28 fn n_glwe(&self) -> Degree {
29 self.n_glwe
30 }
31
32 fn n_lwe(&self) -> Degree {
33 self.n_lwe
34 }
35}
36
37impl GGSWInfos for BlindRotationKeyLayout {
38 fn dsize(&self) -> Dsize {
39 Dsize(1)
40 }
41
42 fn dnum(&self) -> Dnum {
43 self.dnum
44 }
45}
46
47impl GLWEInfos for BlindRotationKeyLayout {
48 fn rank(&self) -> Rank {
49 self.rank
50 }
51}
52
53impl LWEInfos for BlindRotationKeyLayout {
54 fn base2k(&self) -> Base2K {
55 self.base2k
56 }
57
58 fn k(&self) -> TorusPrecision {
59 self.k
60 }
61
62 fn n(&self) -> Degree {
63 self.n_glwe
64 }
65}
66
67pub trait BlindRotationKeyInfos
68where
69 Self: GGSWInfos,
70{
71 fn n_glwe(&self) -> Degree;
72 fn n_lwe(&self) -> Degree;
73}
74
75pub trait BlindRotationKeyAlloc {
76 fn alloc<A>(infos: &A) -> Self
77 where
78 A: BlindRotationKeyInfos;
79}
80
81#[derive(Clone)]
82pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> {
83 pub(crate) keys: Vec<GGSW<D>>,
84 pub(crate) dist: Distribution,
85 pub(crate) _phantom: PhantomData<BRT>,
86}
87
88pub trait BlindRotationKeyFactory<BRA: BlindRotationAlgo> {
89 fn blind_rotation_key_alloc<A>(infos: &A) -> BlindRotationKey<Vec<u8>, BRA>
90 where
91 A: BlindRotationKeyInfos;
92}
93
94impl<BRA: BlindRotationAlgo> BlindRotationKey<Vec<u8>, BRA>
95where
96 Self: BlindRotationKeyFactory<BRA>,
97{
98 pub fn alloc<A>(infos: &A) -> BlindRotationKey<Vec<u8>, BRA>
99 where
100 A: BlindRotationKeyInfos,
101 {
102 Self::blind_rotation_key_alloc(infos)
103 }
104}
105
106impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKey<D, BRT> {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 write!(f, "{self}")
109 }
110}
111
112impl<D: Data, BRT: BlindRotationAlgo> PartialEq for BlindRotationKey<D, BRT> {
113 fn eq(&self, other: &Self) -> bool {
114 if self.keys.len() != other.keys.len() {
115 return false;
116 }
117 for (a, b) in self.keys.iter().zip(other.keys.iter()) {
118 if a != b {
119 return false;
120 }
121 }
122
123 self.dist == other.dist && self._phantom == other._phantom
124 }
125}
126
127impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKey<D, BRT> {}
128
129impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKey<D, BRT> {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 for (i, key) in self.keys.iter().enumerate() {
132 write!(f, "key[{i}]: {key}")?;
133 }
134 writeln!(f, "{:?}", self.dist)
135 }
136}
137
138impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKey<D, BRT> {
139 fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
140 self.keys.iter_mut().for_each(|key| key.fill_uniform(log_bound, source));
141 }
142}
143
144impl<D: DataMut, BRT: BlindRotationAlgo> ReaderFrom for BlindRotationKey<D, BRT> {
145 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
146 match Distribution::read_from(reader) {
147 Ok(dist) => self.dist = dist,
148 Err(e) => return Err(e),
149 }
150 let len: usize = reader.read_u64::<LittleEndian>()? as usize;
151 if self.keys.len() != len {
152 return Err(std::io::Error::new(
153 std::io::ErrorKind::InvalidData,
154 format!("self.keys.len()={} != read len={}", self.keys.len(), len),
155 ));
156 }
157 for key in &mut self.keys {
158 key.read_from(reader)?;
159 }
160 Ok(())
161 }
162}
163
164impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKey<D, BRT> {
165 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
166 match self.dist.write_to(writer) {
167 Ok(()) => {}
168 Err(e) => return Err(e),
169 }
170 writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
171 for key in &self.keys {
172 key.write_to(writer)?;
173 }
174 Ok(())
175 }
176}
177
178impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKey<D, BRT> {
179 fn n_glwe(&self) -> Degree {
180 self.n()
181 }
182
183 fn n_lwe(&self) -> Degree {
184 Degree(self.keys.len() as u32)
185 }
186}
187
188impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKey<D, BRT> {
189 pub fn block_size(&self) -> usize {
190 match self.dist {
191 Distribution::BinaryBlock(value) => value,
192 _ => 1,
193 }
194 }
195}
196
197impl<D: DataRef, BRT: BlindRotationAlgo> LWEInfos for BlindRotationKey<D, BRT> {
198 fn base2k(&self) -> Base2K {
199 self.keys[0].base2k()
200 }
201
202 fn k(&self) -> TorusPrecision {
203 self.keys[0].k()
204 }
205
206 fn n(&self) -> Degree {
207 self.keys[0].n()
208 }
209
210 fn size(&self) -> usize {
211 self.keys[0].size()
212 }
213}
214
215impl<D: DataRef, BRT: BlindRotationAlgo> GLWEInfos for BlindRotationKey<D, BRT> {
216 fn rank(&self) -> Rank {
217 self.keys[0].rank()
218 }
219}
220impl<D: DataRef, BRT: BlindRotationAlgo> GGSWInfos for BlindRotationKey<D, BRT> {
221 fn dsize(&self) -> poulpy_core::layouts::Dsize {
222 Dsize(1)
223 }
224
225 fn dnum(&self) -> Dnum {
226 self.keys[0].dnum()
227 }
228}