arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/mat_znx_dft.rs
base2k/src/mat_znx_dft.rsRaw
  1use crate::znx_base::{GetZnxBase, ZnxBase, ZnxInfos, ZnxLayout, ZnxSliceSize};
  2use crate::{Backend, FFT64, Module, alloc_aligned};
  3use std::marker::PhantomData;
  4
  5/// Vector Matrix Product Prepared Matrix: a vector of [VecZnx],
  6/// stored as a 3D matrix in the DFT domain in a single contiguous array.
  7/// Each col of the [MatZnxDft] can be seen as a collection of [VecZnxDft].
  8///
  9/// [MatZnxDft] is used to permform a vector matrix product between a [VecZnx]/[VecZnxDft] and a [MatZnxDft].
 10/// See the trait [MatZnxDftOps] for additional information.
 11pub struct MatZnxDft<B: Backend> {
 12    pub inner: ZnxBase,
 13    pub cols_in: usize,
 14    pub cols_out: usize,
 15    _marker: PhantomData<B>,
 16}
 17
 18impl<B: Backend> GetZnxBase for MatZnxDft<B> {
 19    fn znx(&self) -> &ZnxBase {
 20        &self.inner
 21    }
 22
 23    fn znx_mut(&mut self) -> &mut ZnxBase {
 24        &mut self.inner
 25    }
 26}
 27
 28impl<B: Backend> ZnxInfos for MatZnxDft<B> {}
 29
 30impl ZnxSliceSize for MatZnxDft<FFT64> {
 31    fn sl(&self) -> usize {
 32        self.n()
 33    }
 34}
 35
 36impl ZnxLayout for MatZnxDft<FFT64> {
 37    type Scalar = f64;
 38}
 39
 40impl<B: Backend> MatZnxDft<B> {
 41    pub fn new(module: &Module<B>, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
 42        let bytes: Vec<u8> = alloc_aligned(Self::bytes_of(module, rows, cols_in, cols_out, size));
 43        Self::from_bytes(module, rows, cols_in, cols_out, size, bytes)
 44    }
 45
 46    pub fn from_bytes(module: &Module<B>, rows: usize, cols_in: usize, cols_out: usize, size: usize, mut bytes: Vec<u8>) -> Self {
 47        let mut mat: MatZnxDft<B> = Self::from_bytes_borrow(module, rows, cols_in, cols_out, size, &mut bytes);
 48        mat.znx_mut().data = bytes;
 49        mat
 50    }
 51
 52    pub fn from_bytes_borrow(
 53        module: &Module<B>,
 54        rows: usize,
 55        cols_in: usize,
 56        cols_out: usize,
 57        size: usize,
 58        bytes: &mut [u8],
 59    ) -> Self {
 60        debug_assert_eq!(
 61            bytes.len(),
 62            Self::bytes_of(module, rows, cols_in, cols_out, size)
 63        );
 64        Self {
 65            inner: ZnxBase::from_bytes_borrow(module.n(), rows, cols_out, size, bytes),
 66            cols_in: cols_in,
 67            cols_out: cols_out,
 68            _marker: PhantomData,
 69        }
 70    }
 71
 72    pub fn bytes_of(module: &Module<B>, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
 73        unsafe {
 74            crate::ffi::vmp::bytes_of_vmp_pmat(
 75                module.ptr,
 76                (rows * cols_in) as u64,
 77                (size * cols_out) as u64,
 78            ) as usize
 79        }
 80    }
 81
 82    pub fn cols_in(&self) -> usize {
 83        self.cols_in
 84    }
 85
 86    pub fn cols_out(&self) -> usize {
 87        self.cols_out
 88    }
 89}
 90
 91impl MatZnxDft<FFT64> {
 92    /// Returns a copy of the backend array at index (i, j) of the [MatZnxDft].
 93    ///
 94    /// # Arguments
 95    ///
 96    /// * `row`: row index (i).
 97    /// * `col`: col index (j).
 98    #[allow(dead_code)]
 99    fn at(&self, row: usize, col: usize) -> Vec<f64> {
100        let n: usize = self.n();
101
102        let mut res: Vec<f64> = alloc_aligned(n);
103
104        if n < 8 {
105            res.copy_from_slice(&self.raw()[(row + col * self.rows()) * n..(row + col * self.rows()) * (n + 1)]);
106        } else {
107            (0..n >> 3).for_each(|blk| {
108                res[blk * 8..(blk + 1) * 8].copy_from_slice(&self.at_block(row, col, blk)[..8]);
109            });
110        }
111
112        res
113    }
114
115    #[allow(dead_code)]
116    fn at_block(&self, row: usize, col: usize, blk: usize) -> &[f64] {
117        let nrows: usize = self.rows();
118        let nsize: usize = self.size();
119        if col == (nsize - 1) && (nsize & 1 == 1) {
120            &self.raw()[blk * nrows * nsize * 8 + col * nrows * 8 + row * 8..]
121        } else {
122            &self.raw()[blk * nrows * nsize * 8 + (col / 2) * (2 * nrows) * 8 + row * 2 * 8 + (col % 2) * 8..]
123        }
124    }
125}