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