arnaucube
arnaucube/poulpyPublic Self-hosted repository
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}