arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/mat_znx_dft.rs
base2k/src/mat_znx_dft.rsRaw
  1use crate::znx_base::ZnxInfos;
  2use crate::{Backend, DataView, DataViewMut, FFT64, Module, ZnxView, 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<D, B> {
 12    data: D,
 13    n: usize,
 14    size: usize,
 15    rows: usize,
 16    cols_in: usize,
 17    cols_out: usize,
 18    _marker: PhantomData<B>,
 19}
 20
 21impl<D, B> ZnxInfos for MatZnxDft<D, B> {
 22    fn cols(&self) -> usize {
 23        self.cols_in
 24    }
 25
 26    fn rows(&self) -> usize {
 27        self.rows
 28    }
 29
 30    fn n(&self) -> usize {
 31        self.n
 32    }
 33
 34    fn size(&self) -> usize {
 35        self.size
 36    }
 37
 38    fn sl(&self) -> usize {
 39        self.n()
 40    }
 41}
 42
 43impl<D, B> DataView for MatZnxDft<D, B> {
 44    type D = D;
 45    fn data(&self) -> &Self::D {
 46        &self.data
 47    }
 48}
 49
 50impl<D, B> DataViewMut for MatZnxDft<D, B> {
 51    fn data_mut(&mut self) -> &mut Self::D {
 52        &mut self.data
 53    }
 54}
 55
 56impl<D: AsRef<[u8]>> ZnxView for MatZnxDft<D, FFT64> {
 57    type Scalar = f64;
 58}
 59
 60impl<D, B> MatZnxDft<D, B> {
 61    pub(crate) fn cols_in(&self) -> usize {
 62        self.cols_in
 63    }
 64
 65    pub(crate) fn cols_out(&self) -> usize {
 66        self.cols_out
 67    }
 68}
 69
 70impl<D: From<Vec<u8>>, B: Backend> MatZnxDft<D, B> {
 71    pub(crate) fn bytes_of(module: &Module<B>, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
 72        unsafe {
 73            crate::ffi::vmp::bytes_of_vmp_pmat(
 74                module.ptr,
 75                (rows * cols_in) as u64,
 76                (size * cols_out) as u64,
 77            ) as usize
 78        }
 79    }
 80
 81    pub(crate) fn new(module: &Module<B>, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
 82        let data: Vec<u8> = alloc_aligned(Self::bytes_of(module, rows, cols_in, cols_out, size));
 83        Self {
 84            data: data.into(),
 85            n: module.n(),
 86            size,
 87            rows,
 88            cols_in,
 89            cols_out,
 90            _marker: PhantomData,
 91        }
 92    }
 93
 94    pub(crate) fn new_from_bytes(
 95        module: &Module<B>,
 96        rows: usize,
 97        cols_in: usize,
 98        cols_out: usize,
 99        size: usize,
100        bytes: impl Into<Vec<u8>>,
101    ) -> Self {
102        let data: Vec<u8> = bytes.into();
103        assert!(data.len() == Self::bytes_of(module, rows, cols_in, cols_out, size));
104        Self {
105            data: data.into(),
106            n: module.n(),
107            size,
108            rows,
109            cols_in,
110            cols_out,
111            _marker: PhantomData,
112        }
113    }
114}
115
116impl<D: AsRef<[u8]>> MatZnxDft<D, FFT64> {
117    /// Returns a copy of the backend array at index (i, j) of the [MatZnxDft].
118    ///
119    /// # Arguments
120    ///
121    /// * `row`: row index (i).
122    /// * `col`: col index (j).
123    #[allow(dead_code)]
124    fn at(&self, row: usize, col: usize) -> Vec<f64> {
125        let n: usize = self.n();
126
127        let mut res: Vec<f64> = alloc_aligned(n);
128
129        if n < 8 {
130            res.copy_from_slice(&self.raw()[(row + col * self.rows()) * n..(row + col * self.rows()) * (n + 1)]);
131        } else {
132            (0..n >> 3).for_each(|blk| {
133                res[blk * 8..(blk + 1) * 8].copy_from_slice(&self.at_block(row, col, blk)[..8]);
134            });
135        }
136
137        res
138    }
139
140    #[allow(dead_code)]
141    fn at_block(&self, row: usize, col: usize, blk: usize) -> &[f64] {
142        let nrows: usize = self.rows();
143        let nsize: usize = self.size();
144        if col == (nsize - 1) && (nsize & 1 == 1) {
145            &self.raw()[blk * nrows * nsize * 8 + col * nrows * 8 + row * 8..]
146        } else {
147            &self.raw()[blk * nrows * nsize * 8 + (col / 2) * (2 * nrows) * 8 + row * 2 * 8 + (col % 2) * 8..]
148        }
149    }
150}
151
152pub type MatZnxDftAllocOwned<B> = MatZnxDft<Vec<u8>, B>;
153
154impl<B> MatZnxDft<Vec<u8>, B> {
155    pub fn to_mut(&mut self) -> MatZnxDft<&mut [u8], B> {
156        MatZnxDft {
157            data: self.data.as_mut_slice(),
158            n: self.n,
159            size: self.size,
160            rows: self.rows,
161            cols_in: self.cols_in,
162            cols_out: self.cols_out,
163            _marker: PhantomData,
164        }
165    }
166
167    pub fn to_ref(&self) -> MatZnxDft<&[u8], B> {
168        MatZnxDft {
169            data: self.data.as_slice(),
170            n: self.n,
171            size: self.size,
172            rows: self.rows,
173            cols_in: self.cols_in,
174            cols_out: self.cols_out,
175            _marker: PhantomData,
176        }
177    }
178}