arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/vector_matrix_product.rs
base2k/src/vector_matrix_product.rsRaw
  1use crate::ffi::vmp::{
  2    delete_vmp_pmat, new_vmp_pmat, vmp_apply_dft, vmp_apply_dft_tmp_bytes, vmp_apply_dft_to_dft,
  3    vmp_apply_dft_to_dft_tmp_bytes, vmp_pmat_t, vmp_prepare_contiguous,
  4    vmp_prepare_contiguous_tmp_bytes, vmp_prepare_dblptr,
  5};
  6use crate::{Module, VecZnx, VecZnxDft};
  7
  8pub struct VmpPMat {
  9    pub data: *mut vmp_pmat_t,
 10    pub rows: usize,
 11    pub cols: usize,
 12    pub n: usize,
 13}
 14
 15impl VmpPMat {
 16    pub fn data(&self) -> *mut vmp_pmat_t {
 17        self.data
 18    }
 19
 20    pub fn rows(&self) -> usize {
 21        self.rows
 22    }
 23
 24    pub fn cols(&self) -> usize {
 25        self.cols
 26    }
 27
 28    pub fn n(&self) -> usize {
 29        self.n
 30    }
 31
 32    pub fn as_f64(&self) -> &[f64] {
 33        let ptr: *const f64 = self.data as *const f64;
 34        let len: usize = (self.rows() * self.cols() * self.n() * 8) / std::mem::size_of::<f64>();
 35        unsafe { &std::slice::from_raw_parts(ptr, len) }
 36    }
 37
 38    pub fn get_addr(&self, row: usize, col: usize, blk: usize) -> &[f64] {
 39        let nrows: usize = self.rows();
 40        let ncols: usize = self.cols();
 41        if col == (ncols - 1) && (ncols & 1 == 1) {
 42            &self.as_f64()[blk * nrows * ncols * 8 + col * nrows * 8 + row * 8..]
 43        } else {
 44            &self.as_f64()[blk * nrows * ncols * 8
 45                + (col / 2) * (2 * nrows) * 8
 46                + row * 2 * 8
 47                + (col % 2) * 8..]
 48        }
 49    }
 50
 51    pub fn at(&self, row: usize, col: usize) -> Vec<f64> {
 52        //assert!(row <= self.rows && col <= self.cols);
 53
 54        let mut res: Vec<f64> = vec![f64::default(); self.n];
 55
 56        if self.n < 8 {
 57            res.copy_from_slice(
 58                &self.as_f64()[(row + col * self.rows()) * self.n()
 59                    ..(row + col * self.rows()) * (self.n() + 1)],
 60            );
 61        } else {
 62            (0..self.n >> 3).for_each(|blk| {
 63                res[blk * 8..(blk + 1) * 8].copy_from_slice(&self.get_addr(row, col, blk)[..8]);
 64            });
 65        }
 66
 67        res
 68    }
 69
 70    pub fn at_mut(&self, row: usize, col: usize) -> &mut [f64] {
 71        assert!(row <= self.rows && col <= self.cols);
 72        let idx: usize = col * (self.n / 2 * self.rows) + row * (self.n >> 1);
 73        let ptr: *mut f64 = self.data as *mut f64;
 74        let len: usize = (self.rows() * self.cols() * self.n() * 8) / std::mem::size_of::<f64>();
 75        unsafe { &mut std::slice::from_raw_parts_mut(ptr, len)[idx..idx + self.n] }
 76    }
 77
 78    pub fn delete(self) {
 79        unsafe { delete_vmp_pmat(self.data) };
 80        drop(self);
 81    }
 82}
 83
 84impl Module {
 85    pub fn new_vmp_pmat(&self, rows: usize, cols: usize) -> VmpPMat {
 86        unsafe {
 87            VmpPMat {
 88                data: new_vmp_pmat(self.0, rows as u64, cols as u64),
 89                rows,
 90                cols,
 91                n: self.n(),
 92            }
 93        }
 94    }
 95
 96    pub fn vmp_prepare_contiguous_tmp_bytes(&self, rows: usize, cols: usize) -> usize {
 97        unsafe { vmp_prepare_contiguous_tmp_bytes(self.0, rows as u64, cols as u64) as usize }
 98    }
 99
100    pub fn vmp_prepare_contiguous(&self, b: &mut VmpPMat, a: &[i64], buf: &mut [u8]) {
101        unsafe {
102            vmp_prepare_contiguous(
103                self.0,
104                b.data(),
105                a.as_ptr(),
106                b.rows() as u64,
107                b.cols() as u64,
108                buf.as_mut_ptr(),
109            );
110        }
111    }
112
113    pub fn vmp_prepare_dblptr(&self, b: &mut VmpPMat, a: &Vec<&Vec<i64>>, buf: &mut [u8]) {
114        let ptrs: Vec<*const i64> = a.iter().map(|v| v.as_ptr()).collect();
115
116        unsafe {
117            vmp_prepare_dblptr(
118                self.0,
119                b.data(),
120                ptrs.as_ptr(),
121                b.rows() as u64,
122                b.cols() as u64,
123                buf.as_mut_ptr(),
124            );
125        }
126    }
127
128    pub fn vmp_apply_dft_tmp_bytes(
129        &self,
130        c_limbs: usize,
131        a_limbs: usize,
132        rows: usize,
133        cols: usize,
134    ) -> usize {
135        unsafe {
136            vmp_apply_dft_tmp_bytes(
137                self.0,
138                c_limbs as u64,
139                a_limbs as u64,
140                rows as u64,
141                cols as u64,
142            ) as usize
143        }
144    }
145
146    pub fn vmp_apply_dft(&self, c: &mut VecZnxDft, a: &VecZnx, b: &VmpPMat, buf: &mut [u8]) {
147        unsafe {
148            vmp_apply_dft(
149                self.0,
150                c.0,
151                c.limbs() as u64,
152                a.as_ptr(),
153                a.limbs() as u64,
154                a.n() as u64,
155                b.data(),
156                b.rows() as u64,
157                b.cols() as u64,
158                buf.as_mut_ptr(),
159            )
160        }
161    }
162
163    pub fn vmp_apply_dft_to_dft_tmp_bytes(
164        &self,
165        c_limbs: usize,
166        a_limbs: usize,
167        rows: usize,
168        cols: usize,
169    ) -> usize {
170        unsafe {
171            vmp_apply_dft_to_dft_tmp_bytes(
172                self.0,
173                c_limbs as u64,
174                a_limbs as u64,
175                rows as u64,
176                cols as u64,
177            ) as usize
178        }
179    }
180
181    pub fn vmp_apply_dft_to_dft(
182        &self,
183        c: &mut VecZnxDft,
184        a: &VecZnxDft,
185        b: &VmpPMat,
186        buf: &mut [u8],
187    ) {
188        unsafe {
189            vmp_apply_dft_to_dft(
190                self.0,
191                c.0,
192                c.limbs() as u64,
193                a.0,
194                a.limbs() as u64,
195                b.data(),
196                b.rows() as u64,
197                b.cols() as u64,
198                buf.as_mut_ptr(),
199            )
200        }
201    }
202
203    pub fn vmp_apply_dft_to_dft_inplace(&self, b: &mut VecZnxDft, a: &VmpPMat, buf: &mut [u8]) {
204        unsafe {
205            vmp_apply_dft_to_dft(
206                self.0,
207                b.0,
208                b.limbs() as u64,
209                b.0,
210                b.limbs() as u64,
211                a.data(),
212                a.rows() as u64,
213                a.cols() as u64,
214                buf.as_mut_ptr(),
215            )
216        }
217    }
218}
219
220pub struct Matrix3D<T> {
221    pub data: Vec<T>,
222    pub rows: usize,
223    pub cols: usize,
224    pub n: usize,
225}
226
227impl<T: Default + Clone + std::marker::Copy> Matrix3D<T> {
228    pub fn new(rows: usize, cols: usize, n: usize) -> Self {
229        let size = rows * cols * n;
230        Self {
231            data: vec![T::default(); size],
232            rows,
233            cols,
234            n,
235        }
236    }
237
238    pub fn at(&self, row: usize, col: usize) -> &[T] {
239        assert!(row <= self.rows && col <= self.cols);
240        let idx: usize = col * (self.n * self.rows) + row * self.n;
241        &self.data[idx..idx + self.n]
242    }
243
244    pub fn at_mut(&mut self, row: usize, col: usize) -> &mut [T] {
245        assert!(row <= self.rows && col <= self.cols);
246        let idx: usize = col * (self.n * self.rows) + row * self.n;
247        &mut self.data[idx..idx + self.n]
248    }
249
250    pub fn set_col(&mut self, col: usize, a: &[T]) {
251        let idx: usize = col * (self.n * self.rows);
252        self.data[idx..idx + self.rows * self.n].copy_from_slice(a);
253    }
254}