poulpy/base2k/src/mat_znx_dft.rs
base2k/src/mat_znx_dft.rsRaw
1use crate::znx_base::{GetZnxBase, ZnxBase, 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 // pub fn from_bytes_borrow(
116 // module: &Module<B>,
117 // rows: usize,
118 // cols_in: usize,
119 // cols_out: usize,
120 // size: usize,
121 // bytes: &mut [u8],
122 // ) -> Self {
123 // debug_assert_eq!(
124 // bytes.len(),
125 // Self::bytes_of(module, rows, cols_in, cols_out, size)
126 // );
127 // Self {
128 // inner: ZnxBase::from_bytes_borrow(module.n(), rows, cols_out, size, bytes),
129 // cols_in: cols_in,
130 // cols_out: cols_out,
131 // _marker: PhantomData,
132 // }
133 // }
134}
135
136impl<D: AsRef<[u8]>> MatZnxDft<D, FFT64> {
137 /// Returns a copy of the backend array at index (i, j) of the [MatZnxDft].
138 ///
139 /// # Arguments
140 ///
141 /// * `row`: row index (i).
142 /// * `col`: col index (j).
143 #[allow(dead_code)]
144 fn at(&self, row: usize, col: usize) -> Vec<f64> {
145 let n: usize = self.n();
146
147 let mut res: Vec<f64> = alloc_aligned(n);
148
149 if n < 8 {
150 res.copy_from_slice(&self.raw()[(row + col * self.rows()) * n..(row + col * self.rows()) * (n + 1)]);
151 } else {
152 (0..n >> 3).for_each(|blk| {
153 res[blk * 8..(blk + 1) * 8].copy_from_slice(&self.at_block(row, col, blk)[..8]);
154 });
155 }
156
157 res
158 }
159
160 #[allow(dead_code)]
161 fn at_block(&self, row: usize, col: usize, blk: usize) -> &[f64] {
162 let nrows: usize = self.rows();
163 let nsize: usize = self.size();
164 if col == (nsize - 1) && (nsize & 1 == 1) {
165 &self.raw()[blk * nrows * nsize * 8 + col * nrows * 8 + row * 8..]
166 } else {
167 &self.raw()[blk * nrows * nsize * 8 + (col / 2) * (2 * nrows) * 8 + row * 2 * 8 + (col % 2) * 8..]
168 }
169 }
170}
171
172pub type MatZnxDftAllocOwned<B> = MatZnxDft<Vec<u8>, B>;