arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/gglwe/keyswitch_key.rs
core/src/gglwe/keyswitch_key.rsRaw
  1use backend::hal::{
  2    api::{MatZnxAlloc, MatZnxAllocBytes},
  3    layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, Scratch, VmpPMat, WriterTo},
  4};
  5
  6use crate::{GGLWECiphertext, GGLWECiphertextExec, GGLWEExecLayoutFamily, GLWECiphertext, Infos};
  7
  8#[derive(PartialEq, Eq)]
  9pub struct GLWESwitchingKey<D: Data> {
 10    pub(crate) key: GGLWECiphertext<D>,
 11    pub(crate) sk_in_n: usize,  // Degree of sk_in
 12    pub(crate) sk_out_n: usize, // Degree of sk_out
 13}
 14
 15impl GLWESwitchingKey<Vec<u8>> {
 16    pub fn alloc<B: Backend>(
 17        module: &Module<B>,
 18        basek: usize,
 19        k: usize,
 20        rows: usize,
 21        digits: usize,
 22        rank_in: usize,
 23        rank_out: usize,
 24    ) -> Self
 25    where
 26        Module<B>: MatZnxAlloc,
 27    {
 28        GLWESwitchingKey {
 29            key: GGLWECiphertext::alloc(module, basek, k, rows, digits, rank_in, rank_out),
 30            sk_in_n: 0,
 31            sk_out_n: 0,
 32        }
 33    }
 34
 35    pub fn bytes_of<B: Backend>(
 36        module: &Module<B>,
 37        basek: usize,
 38        k: usize,
 39        rows: usize,
 40        digits: usize,
 41        rank_in: usize,
 42        rank_out: usize,
 43    ) -> usize
 44    where
 45        Module<B>: MatZnxAllocBytes,
 46    {
 47        GGLWECiphertext::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
 48    }
 49}
 50
 51impl<D: Data> Infos for GLWESwitchingKey<D> {
 52    type Inner = MatZnx<D>;
 53
 54    fn inner(&self) -> &Self::Inner {
 55        self.key.inner()
 56    }
 57
 58    fn basek(&self) -> usize {
 59        self.key.basek()
 60    }
 61
 62    fn k(&self) -> usize {
 63        self.key.k()
 64    }
 65}
 66
 67impl<D: Data> GLWESwitchingKey<D> {
 68    pub fn rank(&self) -> usize {
 69        self.key.data.cols_out() - 1
 70    }
 71
 72    pub fn rank_in(&self) -> usize {
 73        self.key.data.cols_in()
 74    }
 75
 76    pub fn rank_out(&self) -> usize {
 77        self.key.data.cols_out() - 1
 78    }
 79
 80    pub fn digits(&self) -> usize {
 81        self.key.digits()
 82    }
 83
 84    pub fn sk_degree_in(&self) -> usize {
 85        self.sk_in_n
 86    }
 87
 88    pub fn sk_degree_out(&self) -> usize {
 89        self.sk_out_n
 90    }
 91}
 92
 93impl<D: DataRef> GLWESwitchingKey<D> {
 94    pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
 95        self.key.at(row, col)
 96    }
 97}
 98
 99impl<D: DataMut> GLWESwitchingKey<D> {
100    pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
101        self.key.at_mut(row, col)
102    }
103}
104
105use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
106
107impl<D: DataMut> ReaderFrom for GLWESwitchingKey<D> {
108    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
109        self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize;
110        self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize;
111        self.key.read_from(reader)
112    }
113}
114
115impl<D: DataRef> WriterTo for GLWESwitchingKey<D> {
116    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
117        writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?;
118        writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?;
119        self.key.write_to(writer)
120    }
121}
122
123#[derive(PartialEq, Eq)]
124pub struct GLWESwitchingKeyExec<D: Data, B: Backend> {
125    pub(crate) key: GGLWECiphertextExec<D, B>,
126    pub(crate) sk_in_n: usize,  // Degree of sk_in
127    pub(crate) sk_out_n: usize, // Degree of sk_out
128}
129
130impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
131    pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
132    where
133        Module<B>: GGLWEExecLayoutFamily<B>,
134    {
135        GLWESwitchingKeyExec::<Vec<u8>, B> {
136            key: GGLWECiphertextExec::alloc(module, basek, k, rows, digits, rank_in, rank_out),
137            sk_in_n: 0,
138            sk_out_n: 0,
139        }
140    }
141
142    pub fn bytes_of(
143        module: &Module<B>,
144        basek: usize,
145        k: usize,
146        rows: usize,
147        digits: usize,
148        rank_in: usize,
149        rank_out: usize,
150    ) -> usize
151    where
152        Module<B>: GGLWEExecLayoutFamily<B>,
153    {
154        GGLWECiphertextExec::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
155    }
156
157    pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
158    where
159        Module<B>: GGLWEExecLayoutFamily<B>,
160    {
161        let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
162            module,
163            other.basek(),
164            other.k(),
165            other.rows(),
166            other.digits(),
167            other.rank_in(),
168            other.rank_out(),
169        );
170        ksk_exec.prepare(module, other, scratch);
171        ksk_exec
172    }
173}
174
175impl<D: Data, B: Backend> Infos for GLWESwitchingKeyExec<D, B> {
176    type Inner = VmpPMat<D, B>;
177
178    fn inner(&self) -> &Self::Inner {
179        self.key.inner()
180    }
181
182    fn basek(&self) -> usize {
183        self.key.basek()
184    }
185
186    fn k(&self) -> usize {
187        self.key.k()
188    }
189}
190
191impl<D: Data, B: Backend> GLWESwitchingKeyExec<D, B> {
192    pub fn rank(&self) -> usize {
193        self.key.data.cols_out() - 1
194    }
195
196    pub fn rank_in(&self) -> usize {
197        self.key.data.cols_in()
198    }
199
200    pub fn rank_out(&self) -> usize {
201        self.key.data.cols_out() - 1
202    }
203
204    pub fn digits(&self) -> usize {
205        self.key.digits()
206    }
207
208    pub fn sk_degree_in(&self) -> usize {
209        self.sk_in_n
210    }
211
212    pub fn sk_degree_out(&self) -> usize {
213        self.sk_out_n
214    }
215}
216
217impl<D: DataMut, B: Backend> GLWESwitchingKeyExec<D, B> {
218    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
219    where
220        DataOther: DataRef,
221        Module<B>: GGLWEExecLayoutFamily<B>,
222    {
223        self.key.prepare(module, &other.key, scratch);
224        self.sk_in_n = other.sk_in_n;
225        self.sk_out_n = other.sk_out_n;
226    }
227}