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::{Backend, Scratch, VecZnxBigToMut, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef, ZnxSliceSize};
  5use crate::{FFT64, Module, ZnxView, ZnxViewMut, ZnxZero};
  6use std::cmp::min;
  7
  8pub trait VecZnxDftAlloc<B: Backend> {
  9    /// Allocates a vector Z[X]/(X^N+1) that stores normalized in the DFT space.
 10    fn new_vec_znx_dft(&self, cols: usize, size: usize) -> VecZnxDftOwned<B>;
 11
 12    /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
 13    ///
 14    /// Behavior: takes ownership of the backing array.
 15    ///
 16    /// # Arguments
 17    ///
 18    /// * `cols`: the number of cols of the [VecZnxDft].
 19    /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
 20    ///
 21    /// # Panics
 22    /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
 23    fn new_vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B>;
 24
 25    /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
 26    ///
 27    /// # Arguments
 28    ///
 29    /// * `cols`: the number of cols of the [VecZnxDft].
 30    /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
 31    ///
 32    /// # Panics
 33    /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
 34    fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize;
 35}
 36
 37pub trait VecZnxDftOps<B: Backend> {
 38    /// Returns the minimum number of bytes necessary to allocate
 39    /// a new [VecZnxDft] through [VecZnxDft::from_bytes].
 40    fn vec_znx_idft_tmp_bytes(&self) -> usize;
 41
 42    /// b <- IDFT(a), uses a as scratch space.
 43    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_cols: usize)
 44    where
 45        R: VecZnxBigToMut<B>,
 46        A: VecZnxDftToMut<B>;
 47
 48    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
 49    where
 50        R: VecZnxBigToMut<B>,
 51        A: VecZnxDftToRef<B>;
 52
 53    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
 54    where
 55        R: VecZnxDftToMut<B>,
 56        A: VecZnxToRef;
 57}
 58
 59impl<B: Backend> VecZnxDftAlloc<B> for Module<B> {
 60    fn new_vec_znx_dft(&self, cols: usize, size: usize) -> VecZnxDftOwned<B> {
 61        VecZnxDftOwned::new(&self, cols, size)
 62    }
 63
 64    fn new_vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B> {
 65        VecZnxDftOwned::new_from_bytes(self, cols, size, bytes)
 66    }
 67
 68    fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize {
 69        bytes_of_vec_znx_dft(self, cols, size)
 70    }
 71}
 72
 73impl VecZnxDftOps<FFT64> for Module<FFT64> {
 74    fn vec_znx_idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
 75    where
 76        R: VecZnxBigToMut<FFT64>,
 77        A: VecZnxDftToMut<FFT64>,
 78    {
 79        let mut res_mut = res.to_mut();
 80        let mut a_mut = a.to_mut();
 81
 82        let min_size: usize = min(res_mut.size(), a_mut.size());
 83
 84        unsafe {
 85            (0..min_size).for_each(|j| {
 86                vec_znx_dft::vec_znx_idft_tmp_a(
 87                    self.ptr,
 88                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
 89                    1 as u64,
 90                    a_mut.at_mut_ptr(a_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
 91                    1 as u64,
 92                )
 93            });
 94            (min_size..res_mut.size()).for_each(|j| {
 95                res_mut.zero_at(res_col, j);
 96            })
 97        }
 98    }
 99
100    fn vec_znx_idft_tmp_bytes(&self) -> usize {
101        unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.ptr) as usize }
102    }
103
104    /// b <- DFT(a)
105    ///
106    /// # Panics
107    /// If b.cols < a_cols
108    fn vec_znx_dft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
109    where
110        R: VecZnxDftToMut<FFT64>,
111        A: VecZnxToRef,
112    {
113        let mut res_mut = res.to_mut();
114        let a_ref = a.to_ref();
115
116        let min_size: usize = min(res_mut.size(), a_ref.size());
117
118        unsafe {
119            (0..min_size).for_each(|j| {
120                vec_znx_dft::vec_znx_dft(
121                    self.ptr,
122                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
123                    1 as u64,
124                    a_ref.at_ptr(a_col, j),
125                    1 as u64,
126                    a_ref.sl() as u64,
127                )
128            });
129            (min_size..res_mut.size()).for_each(|j| {
130                res_mut.zero_at(res_col, j);
131            });
132        }
133    }
134
135    // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
136    fn vec_znx_idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch)
137    where
138        R: VecZnxBigToMut<FFT64>,
139        A: VecZnxDftToRef<FFT64>,
140    {
141        let mut res_mut = res.to_mut();
142        let a_ref = a.to_ref();
143
144        let (tmp_bytes, _) = scratch.tmp_slice(self.vec_znx_idft_tmp_bytes());
145
146        let min_size: usize = min(res_mut.size(), a_ref.size());
147
148        unsafe {
149            (0..min_size).for_each(|j| {
150                vec_znx_dft::vec_znx_idft(
151                    self.ptr,
152                    res_mut.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
153                    1 as u64,
154                    a_ref.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
155                    1 as u64,
156                    tmp_bytes.as_mut_ptr(),
157                )
158            });
159            (min_size..res_mut.size()).for_each(|j| {
160                res_mut.zero_at(res_col, j);
161            });
162        }
163    }
164}