arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/vec_znx_dft_ops.rs
base2k/src/vec_znx_dft_ops.rsRaw
  1use crate::ffi::{vec_znx_big, vec_znx_dft};
  2use crate::vec_znx_dft::bytes_of_vec_znx_dft;
  3use crate::znx_base::ZnxInfos;
  4use crate::{
  5    Backend, Scratch, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef,
  6    ZnxSliceSize,
  7};
  8use crate::{FFT64, Module, ZnxView, ZnxViewMut, ZnxZero};
  9use std::cmp::min;
 10
 11pub trait VecZnxDftAlloc<B: Backend> {
 12    /// Allocates a vector Z[X]/(X^N+1) that stores normalized in the DFT space.
 13    fn new_vec_znx_dft(&self, cols: usize, size: usize) -> VecZnxDftOwned<B>;
 14
 15    /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
 16    ///
 17    /// Behavior: takes ownership of the backing array.
 18    ///
 19    /// # Arguments
 20    ///
 21    /// * `cols`: the number of cols of the [VecZnxDft].
 22    /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
 23    ///
 24    /// # Panics
 25    /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
 26    fn new_vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B>;
 27
 28    /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
 29    ///
 30    /// # Arguments
 31    ///
 32    /// * `cols`: the number of cols of the [VecZnxDft].
 33    /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
 34    ///
 35    /// # Panics
 36    /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
 37    fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize;
 38}
 39
 40pub trait VecZnxDftOps<B: Backend> {
 41    /// Returns the minimum number of bytes necessary to allocate
 42    /// a new [VecZnxDft] through [VecZnxDft::from_bytes].
 43    fn vec_znx_idft_tmp_bytes(&self) -> usize;
 44
 45    fn vec_znx_dft_add<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
 46    where
 47        R: VecZnxDftToMut<B>,
 48        A: VecZnxDftToRef<B>,
 49        D: VecZnxDftToRef<B>;
 50
 51    fn vec_znx_dft_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
 52    where
 53        R: VecZnxDftToMut<B>,
 54        A: VecZnxDftToRef<B>;
 55
 56    fn vec_znx_dft_copy<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
 57    where
 58        R: VecZnxDftToMut<B>,
 59        A: VecZnxDftToRef<B>;
 60
 61    /// b <- IDFT(a), uses a as scratch space.
 62    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
 63    where
 64        R: VecZnxBigToMut<B>,
 65        A: VecZnxDftToMut<B>;
 66
 67    /// Consumes a to return IDFT(a) in big coeff space.
 68    fn vec_znx_idft_consume<D>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, FFT64>
 69    where
 70        VecZnxDft<D, FFT64>: VecZnxDftToMut<FFT64>;
 71
 72    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
 73    where
 74        R: VecZnxBigToMut<B>,
 75        A: VecZnxDftToRef<B>;
 76
 77    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
 78    where
 79        R: VecZnxDftToMut<B>,
 80        A: VecZnxToRef;
 81}
 82
 83impl<B: Backend> VecZnxDftAlloc<B> for Module<B> {
 84    fn new_vec_znx_dft(&self, cols: usize, size: usize) -> VecZnxDftOwned<B> {
 85        VecZnxDftOwned::new(&self, cols, size)
 86    }
 87
 88    fn new_vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B> {
 89        VecZnxDftOwned::new_from_bytes(self, cols, size, bytes)
 90    }
 91
 92    fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize {
 93        bytes_of_vec_znx_dft(self, cols, size)
 94    }
 95}
 96
 97impl VecZnxDftOps<FFT64> for Module<FFT64> {
 98    fn vec_znx_dft_add<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
 99    where
100        R: VecZnxDftToMut<FFT64>,
101        A: VecZnxDftToRef<FFT64>,
102        D: VecZnxDftToRef<FFT64>,
103    {
104        let mut res_mut: VecZnxDft<&mut [u8], FFT64> = res.to_mut();
105        let a_ref: VecZnxDft<&[u8], FFT64> = a.to_ref();
106        let b_ref: VecZnxDft<&[u8], FFT64> = b.to_ref();
107
108        let min_size: usize = res_mut.size().min(a_ref.size()).min(b_ref.size());
109
110        unsafe {
111            (0..min_size).for_each(|j| {
112                vec_znx_dft::vec_dft_add(
113                    self.ptr,
114                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
115                    1,
116                    a_ref.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
117                    1,
118                    b_ref.at_ptr(b_col, j) as *const vec_znx_dft::vec_znx_dft_t,
119                    1,
120                );
121            });
122        }
123        (min_size..res_mut.size()).for_each(|j| {
124            res_mut.zero_at(res_col, j);
125        })
126    }
127
128    fn vec_znx_dft_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
129    where
130        R: VecZnxDftToMut<FFT64>,
131        A: VecZnxDftToRef<FFT64>,
132    {
133        let mut res_mut: VecZnxDft<&mut [u8], FFT64> = res.to_mut();
134        let a_ref: VecZnxDft<&[u8], FFT64> = a.to_ref();
135
136        let min_size: usize = res_mut.size().min(a_ref.size());
137
138        unsafe {
139            (0..min_size).for_each(|j| {
140                vec_znx_dft::vec_dft_add(
141                    self.ptr,
142                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
143                    1,
144                    res_mut.at_ptr(res_col, j) as *const vec_znx_dft::vec_znx_dft_t,
145                    1,
146                    a_ref.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
147                    1,
148                );
149            });
150        }
151        (min_size..res_mut.size()).for_each(|j| {
152            res_mut.zero_at(res_col, j);
153        })
154    }
155
156    fn vec_znx_dft_copy<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
157    where
158        R: VecZnxDftToMut<FFT64>,
159        A: VecZnxDftToRef<FFT64>,
160    {
161        let mut res_mut: VecZnxDft<&mut [u8], FFT64> = res.to_mut();
162        let a_ref: VecZnxDft<&[u8], FFT64> = a.to_ref();
163
164        let min_size: usize = min(res_mut.size(), a_ref.size());
165
166        (0..min_size).for_each(|j| {
167            res_mut
168                .at_mut(res_col, j)
169                .copy_from_slice(a_ref.at(a_col, j));
170        });
171        (min_size..res_mut.size()).for_each(|j| {
172            res_mut.zero_at(res_col, j);
173        })
174    }
175
176    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
177    where
178        R: VecZnxBigToMut<FFT64>,
179        A: VecZnxDftToMut<FFT64>,
180    {
181        let mut res_mut: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
182        let mut a_mut: VecZnxDft<&mut [u8], FFT64> = a.to_mut();
183
184        let min_size: usize = min(res_mut.size(), a_mut.size());
185
186        unsafe {
187            (0..min_size).for_each(|j| {
188                vec_znx_dft::vec_znx_idft_tmp_a(
189                    self.ptr,
190                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
191                    1 as u64,
192                    a_mut.at_mut_ptr(a_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
193                    1 as u64,
194                )
195            });
196            (min_size..res_mut.size()).for_each(|j| {
197                res_mut.zero_at(res_col, j);
198            })
199        }
200    }
201
202    fn vec_znx_idft_consume<D>(&self, mut a: VecZnxDft<D, FFT64>) -> VecZnxBig<D, FFT64>
203    where
204        VecZnxDft<D, FFT64>: VecZnxDftToMut<FFT64>,
205    {
206        let mut a_mut: VecZnxDft<&mut [u8], FFT64> = a.to_mut();
207
208        unsafe {
209            // Rev col and rows because ZnxDft.sl() >= ZnxBig.sl()
210            (0..a_mut.size()).for_each(|j| {
211                (0..a_mut.cols()).for_each(|i| {
212                    vec_znx_dft::vec_znx_idft_tmp_a(
213                        self.ptr,
214                        a_mut.at_mut_ptr(i, j) as *mut vec_znx_big::vec_znx_big_t,
215                        1 as u64,
216                        a_mut.at_mut_ptr(i, j) as *mut vec_znx_dft::vec_znx_dft_t,
217                        1 as u64,
218                    )
219                });
220            });
221        }
222
223        a.into_big()
224    }
225
226    fn vec_znx_idft_tmp_bytes(&self) -> usize {
227        unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.ptr) as usize }
228    }
229
230    /// b <- DFT(a)
231    ///
232    /// # Panics
233    /// If b.cols < a_col
234    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
235    where
236        R: VecZnxDftToMut<FFT64>,
237        A: VecZnxToRef,
238    {
239        let mut res_mut: VecZnxDft<&mut [u8], FFT64> = res.to_mut();
240        let a_ref: crate::VecZnx<&[u8]> = a.to_ref();
241
242        let min_size: usize = min(res_mut.size(), a_ref.size());
243
244        unsafe {
245            (0..min_size).for_each(|j| {
246                vec_znx_dft::vec_znx_dft(
247                    self.ptr,
248                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
249                    1 as u64,
250                    a_ref.at_ptr(a_col, j),
251                    1 as u64,
252                    a_ref.sl() as u64,
253                )
254            });
255            (min_size..res_mut.size()).for_each(|j| {
256                res_mut.zero_at(res_col, j);
257            });
258        }
259    }
260
261    // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
262    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
263    where
264        R: VecZnxBigToMut<FFT64>,
265        A: VecZnxDftToRef<FFT64>,
266    {
267        let mut res_mut: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
268        let a_ref: VecZnxDft<&[u8], FFT64> = a.to_ref();
269
270        let (tmp_bytes, _) = scratch.tmp_slice(self.vec_znx_idft_tmp_bytes());
271
272        let min_size: usize = min(res_mut.size(), a_ref.size());
273
274        unsafe {
275            (0..min_size).for_each(|j| {
276                vec_znx_dft::vec_znx_idft(
277                    self.ptr,
278                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
279                    1 as u64,
280                    a_ref.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
281                    1 as u64,
282                    tmp_bytes.as_mut_ptr(),
283                )
284            });
285            (min_size..res_mut.size()).for_each(|j| {
286                res_mut.zero_at(res_col, j);
287            });
288        }
289    }
290}