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