arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe_ops.rs
core/src/glwe_ops.rsRaw
  1use backend::{FFT64, Module, Scratch, VecZnx, VecZnxOps, ZnxZero};
  2
  3use crate::{
  4    elem::{Infos, SetMetaData},
  5    glwe_ciphertext::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef},
  6};
  7
  8pub trait GLWEOps: GLWECiphertextToMut + Infos + SetMetaData {
  9    fn add<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
 10    where
 11        A: GLWECiphertextToRef + Infos,
 12        B: GLWECiphertextToRef + Infos,
 13    {
 14        #[cfg(debug_assertions)]
 15        {
 16            assert_eq!(a.n(), module.n());
 17            assert_eq!(b.n(), module.n());
 18            assert_eq!(self.n(), module.n());
 19            assert_eq!(a.basek(), b.basek());
 20            assert!(self.rank() >= a.rank().max(b.rank()));
 21        }
 22
 23        let min_col: usize = a.rank().min(b.rank()) + 1;
 24        let max_col: usize = a.rank().max(b.rank() + 1);
 25        let self_col: usize = self.rank() + 1;
 26
 27        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
 28        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
 29        let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref();
 30
 31        (0..min_col).for_each(|i| {
 32            module.vec_znx_add(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);
 33        });
 34
 35        if a.rank() > b.rank() {
 36            (min_col..max_col).for_each(|i| {
 37                module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
 38            });
 39        } else {
 40            (min_col..max_col).for_each(|i| {
 41                module.vec_znx_copy(&mut self_mut.data, i, &b_ref.data, i);
 42            });
 43        }
 44
 45        let size: usize = self_mut.size();
 46        (max_col..self_col).for_each(|i| {
 47            (0..size).for_each(|j| {
 48                self_mut.data.zero_at(i, j);
 49            });
 50        });
 51
 52        self.set_basek(a.basek());
 53        self.set_k(a.k().max(b.k()));
 54    }
 55
 56    fn add_inplace<A>(&mut self, module: &Module<FFT64>, a: &A)
 57    where
 58        A: GLWECiphertextToRef + Infos,
 59    {
 60        #[cfg(debug_assertions)]
 61        {
 62            assert_eq!(a.n(), module.n());
 63            assert_eq!(self.n(), module.n());
 64            assert_eq!(self.basek(), a.basek());
 65            assert!(self.rank() >= a.rank())
 66        }
 67
 68        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
 69        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
 70
 71        (0..a.rank() + 1).for_each(|i| {
 72            module.vec_znx_add_inplace(&mut self_mut.data, i, &a_ref.data, i);
 73        });
 74
 75        self.set_k(a.k().max(self.k()));
 76    }
 77
 78    fn sub<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
 79    where
 80        A: GLWECiphertextToRef + Infos,
 81        B: GLWECiphertextToRef + Infos,
 82    {
 83        #[cfg(debug_assertions)]
 84        {
 85            assert_eq!(a.n(), module.n());
 86            assert_eq!(b.n(), module.n());
 87            assert_eq!(self.n(), module.n());
 88            assert_eq!(a.basek(), b.basek());
 89            assert!(self.rank() >= a.rank().max(b.rank()));
 90        }
 91
 92        let min_col: usize = a.rank().min(b.rank()) + 1;
 93        let max_col: usize = a.rank().max(b.rank() + 1);
 94        let self_col: usize = self.rank() + 1;
 95
 96        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
 97        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
 98        let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref();
 99
100        (0..min_col).for_each(|i| {
101            module.vec_znx_sub(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);
102        });
103
104        if a.rank() > b.rank() {
105            (min_col..max_col).for_each(|i| {
106                module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
107            });
108        } else {
109            (min_col..max_col).for_each(|i| {
110                module.vec_znx_copy(&mut self_mut.data, i, &b_ref.data, i);
111                module.vec_znx_negate_inplace(&mut self_mut.data, i);
112            });
113        }
114
115        let size: usize = self_mut.size();
116        (max_col..self_col).for_each(|i| {
117            (0..size).for_each(|j| {
118                self_mut.data.zero_at(i, j);
119            });
120        });
121
122        self.set_basek(a.basek());
123        self.set_k(a.k().max(b.k()));
124    }
125
126    fn sub_inplace_ab<A>(&mut self, module: &Module<FFT64>, a: &A)
127    where
128        A: GLWECiphertextToRef + Infos,
129    {
130        #[cfg(debug_assertions)]
131        {
132            assert_eq!(a.n(), module.n());
133            assert_eq!(self.n(), module.n());
134            assert_eq!(self.basek(), a.basek());
135            assert!(self.rank() >= a.rank())
136        }
137
138        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
139        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
140
141        (0..a.rank() + 1).for_each(|i| {
142            module.vec_znx_sub_ab_inplace(&mut self_mut.data, i, &a_ref.data, i);
143        });
144
145        self.set_k(a.k().max(self.k()));
146    }
147
148    fn sub_inplace_ba<A>(&mut self, module: &Module<FFT64>, a: &A)
149    where
150        A: GLWECiphertextToRef + Infos,
151    {
152        #[cfg(debug_assertions)]
153        {
154            assert_eq!(a.n(), module.n());
155            assert_eq!(self.n(), module.n());
156            assert_eq!(self.basek(), a.basek());
157            assert!(self.rank() >= a.rank())
158        }
159
160        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
161        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
162
163        (0..a.rank() + 1).for_each(|i| {
164            module.vec_znx_sub_ba_inplace(&mut self_mut.data, i, &a_ref.data, i);
165        });
166
167        self.set_k(a.k().max(self.k()));
168    }
169
170    fn rotate<A>(&mut self, module: &Module<FFT64>, k: i64, a: &A)
171    where
172        A: GLWECiphertextToRef + Infos,
173    {
174        #[cfg(debug_assertions)]
175        {
176            assert_eq!(a.n(), module.n());
177            assert_eq!(self.n(), module.n());
178            assert_eq!(self.rank(), a.rank())
179        }
180
181        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
182        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
183
184        (0..a.rank() + 1).for_each(|i| {
185            module.vec_znx_rotate(k, &mut self_mut.data, i, &a_ref.data, i);
186        });
187
188        self.set_basek(a.basek());
189        self.set_k(a.k());
190    }
191
192    fn rotate_inplace(&mut self, module: &Module<FFT64>, k: i64) {
193        #[cfg(debug_assertions)]
194        {
195            assert_eq!(self.n(), module.n());
196        }
197
198        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
199
200        (0..self_mut.rank() + 1).for_each(|i| {
201            module.vec_znx_rotate_inplace(k, &mut self_mut.data, i);
202        });
203    }
204
205    fn copy<A>(&mut self, module: &Module<FFT64>, a: &A)
206    where
207        A: GLWECiphertextToRef + Infos,
208    {
209        #[cfg(debug_assertions)]
210        {
211            assert_eq!(self.n(), module.n());
212            assert_eq!(a.n(), module.n());
213            assert_eq!(self.rank(), a.rank());
214        }
215
216        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
217        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
218
219        (0..self_mut.rank() + 1).for_each(|i| {
220            module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
221        });
222
223        self.set_k(a.k());
224        self.set_basek(a.basek());
225    }
226
227    fn rsh(&mut self, k: usize, scratch: &mut Scratch) {
228        let basek: usize = self.basek();
229        let mut self_mut: GLWECiphertext<&mut [u8]> = self.to_mut();
230        self_mut.data.rsh(basek, k, scratch);
231    }
232
233    fn normalize<A>(&mut self, module: &Module<FFT64>, a: &A, scratch: &mut Scratch)
234    where
235        A: GLWECiphertextToRef + Infos,
236    {
237        #[cfg(debug_assertions)]
238        {
239            assert_eq!(self.n(), module.n());
240            assert_eq!(a.n(), module.n());
241            assert_eq!(self.rank(), a.rank());
242        }
243
244        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
245        let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
246
247        (0..self_mut.rank() + 1).for_each(|i| {
248            module.vec_znx_normalize(a.basek(), &mut self_mut.data, i, &a_ref.data, i, scratch);
249        });
250        self.set_basek(a.basek());
251        self.set_k(a.k());
252    }
253
254    fn normalize_inplace(&mut self, module: &Module<FFT64>, scratch: &mut Scratch) {
255        #[cfg(debug_assertions)]
256        {
257            assert_eq!(self.n(), module.n());
258        }
259        let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
260        (0..self_mut.rank() + 1).for_each(|i| {
261            module.vec_znx_normalize_inplace(self_mut.basek(), &mut self_mut.data, i, scratch);
262        });
263    }
264}
265
266impl GLWECiphertext<Vec<u8>> {
267    pub fn rsh_scratch_space(module: &Module<FFT64>) -> usize {
268        VecZnx::rsh_scratch_space(module.n())
269    }
270}