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    /// b <- IDFT(a), uses a as scratch space.
 46    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_cols: usize)
 47    where
 48        R: VecZnxBigToMut<B>,
 49        A: VecZnxDftToMut<B>;
 50
 51    /// Consumes a to return IDFT(a) in big coeff space.
 52    fn vec_znx_idft_consume<D>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, FFT64>
 53    where
 54        VecZnxDft<D, FFT64>: VecZnxDftToMut<FFT64>;
 55
 56    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
 57    where
 58        R: VecZnxBigToMut<B>,
 59        A: VecZnxDftToRef<B>;
 60
 61    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
 62    where
 63        R: VecZnxDftToMut<B>,
 64        A: VecZnxToRef;
 65}
 66
 67impl<B: Backend> VecZnxDftAlloc<B> for Module<B> {
 68    fn new_vec_znx_dft(&self, cols: usize, size: usize) -> VecZnxDftOwned<B> {
 69        VecZnxDftOwned::new(&self, cols, size)
 70    }
 71
 72    fn new_vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B> {
 73        VecZnxDftOwned::new_from_bytes(self, cols, size, bytes)
 74    }
 75
 76    fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize {
 77        bytes_of_vec_znx_dft(self, cols, size)
 78    }
 79}
 80
 81impl VecZnxDftOps<FFT64> for Module<FFT64> {
 82    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
 83    where
 84        R: VecZnxBigToMut<FFT64>,
 85        A: VecZnxDftToMut<FFT64>,
 86    {
 87        let mut res_mut = res.to_mut();
 88        let mut a_mut = a.to_mut();
 89
 90        let min_size: usize = min(res_mut.size(), a_mut.size());
 91
 92        unsafe {
 93            (0..min_size).for_each(|j| {
 94                vec_znx_dft::vec_znx_idft_tmp_a(
 95                    self.ptr,
 96                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
 97                    1 as u64,
 98                    a_mut.at_mut_ptr(a_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
 99                    1 as u64,
100                )
101            });
102            (min_size..res_mut.size()).for_each(|j| {
103                res_mut.zero_at(res_col, j);
104            })
105        }
106    }
107
108    fn vec_znx_idft_consume<D>(&self, mut a: VecZnxDft<D, FFT64>) -> VecZnxBig<D, FFT64>
109    where
110        VecZnxDft<D, FFT64>: VecZnxDftToMut<FFT64>,
111    {
112        let mut a_mut: VecZnxDft<&mut [u8], FFT64> = a.to_mut();
113
114        unsafe {
115            // Rev col and rows because ZnxDft.sl() >= ZnxBig.sl()
116            (0..a_mut.size()).for_each(|j| {
117                (0..a_mut.cols()).for_each(|i| {
118                    vec_znx_dft::vec_znx_idft_tmp_a(
119                        self.ptr,
120                        a_mut.at_mut_ptr(i, j) as *mut vec_znx_big::vec_znx_big_t,
121                        1 as u64,
122                        a_mut.at_mut_ptr(i, j) as *mut vec_znx_dft::vec_znx_dft_t,
123                        1 as u64,
124                    )
125                });
126            });
127        }
128
129        a.into_big()
130    }
131
132    fn vec_znx_idft_tmp_bytes(&self) -> usize {
133        unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.ptr) as usize }
134    }
135
136    /// b <- DFT(a)
137    ///
138    /// # Panics
139    /// If b.cols < a_cols
140    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
141    where
142        R: VecZnxDftToMut<FFT64>,
143        A: VecZnxToRef,
144    {
145        let mut res_mut = res.to_mut();
146        let a_ref = a.to_ref();
147
148        let min_size: usize = min(res_mut.size(), a_ref.size());
149
150        unsafe {
151            (0..min_size).for_each(|j| {
152                vec_znx_dft::vec_znx_dft(
153                    self.ptr,
154                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
155                    1 as u64,
156                    a_ref.at_ptr(a_col, j),
157                    1 as u64,
158                    a_ref.sl() as u64,
159                )
160            });
161            (min_size..res_mut.size()).for_each(|j| {
162                res_mut.zero_at(res_col, j);
163            });
164        }
165    }
166
167    // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
168    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
169    where
170        R: VecZnxBigToMut<FFT64>,
171        A: VecZnxDftToRef<FFT64>,
172    {
173        let mut res_mut = res.to_mut();
174        let a_ref = a.to_ref();
175
176        let (tmp_bytes, _) = scratch.tmp_slice(self.vec_znx_idft_tmp_bytes());
177
178        let min_size: usize = min(res_mut.size(), a_ref.size());
179
180        unsafe {
181            (0..min_size).for_each(|j| {
182                vec_znx_dft::vec_znx_idft(
183                    self.ptr,
184                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
185                    1 as u64,
186                    a_ref.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
187                    1 as u64,
188                    tmp_bytes.as_mut_ptr(),
189                )
190            });
191            (min_size..res_mut.size()).for_each(|j| {
192                res_mut.zero_at(res_col, j);
193            });
194        }
195    }
196}