arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/mat_znx_dft.rs
base2k/src/mat_znx_dft.rsRaw
 1use crate::znx_base::{GetZnxBase, ZnxAlloc, 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    _marker: PhantomData<B>,
14}
15
16impl<B: Backend> GetZnxBase for MatZnxDft<B> {
17    fn znx(&self) -> &ZnxBase {
18        &self.inner
19    }
20
21    fn znx_mut(&mut self) -> &mut ZnxBase {
22        &mut self.inner
23    }
24}
25
26impl<B: Backend> ZnxInfos for MatZnxDft<B> {}
27
28impl ZnxSliceSize for MatZnxDft<FFT64> {
29    fn sl(&self) -> usize {
30        self.n()
31    }
32}
33
34impl ZnxLayout for MatZnxDft<FFT64> {
35    type Scalar = f64;
36}
37
38impl<B: Backend> ZnxAlloc<B> for MatZnxDft<B> {
39    type Scalar = u8;
40
41    fn from_bytes_borrow(module: &Module<B>, rows: usize, cols: usize, size: usize, bytes: &mut [u8]) -> Self {
42        Self {
43            inner: ZnxBase::from_bytes_borrow(module.n(), rows, cols, size, bytes),
44            _marker: PhantomData,
45        }
46    }
47
48    fn bytes_of(module: &Module<B>, rows: usize, cols: usize, size: usize) -> usize {
49        unsafe { crate::ffi::vmp::bytes_of_vmp_pmat(module.ptr, rows as u64, size as u64) as usize * cols }
50    }
51}
52
53impl MatZnxDft<FFT64> {
54    /// Returns a copy of the backend array at index (i, j) of the [MatZnxDft].
55    ///
56    /// # Arguments
57    ///
58    /// * `row`: row index (i).
59    /// * `col`: col index (j).
60    #[allow(dead_code)]
61    fn at(&self, row: usize, col: usize) -> Vec<f64> {
62        let n: usize = self.n();
63
64        let mut res: Vec<f64> = alloc_aligned(n);
65
66        if n < 8 {
67            res.copy_from_slice(&self.raw()[(row + col * self.rows()) * n..(row + col * self.rows()) * (n + 1)]);
68        } else {
69            (0..n >> 3).for_each(|blk| {
70                res[blk * 8..(blk + 1) * 8].copy_from_slice(&self.at_block(row, col, blk)[..8]);
71            });
72        }
73
74        res
75    }
76
77    #[allow(dead_code)]
78    fn at_block(&self, row: usize, col: usize, blk: usize) -> &[f64] {
79        let nrows: usize = self.rows();
80        let nsize: usize = self.size();
81        if col == (nsize - 1) && (nsize & 1 == 1) {
82            &self.raw()[blk * nrows * nsize * 8 + col * nrows * 8 + row * 8..]
83        } else {
84            &self.raw()[blk * nrows * nsize * 8 + (col / 2) * (2 * nrows) * 8 + row * 2 * 8 + (col % 2) * 8..]
85        }
86    }
87}