poulpy/backend/src/hal/layouts/mat_znx.rs
backend/src/hal/layouts/mat_znx.rsRaw
1use crate::{
2 alloc_aligned,
3 hal::{
4 api::{DataView, DataViewMut, FillUniform, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
5 layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, WriterTo},
6 },
7};
8use std::fmt;
9
10use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
11use rand::RngCore;
12use sampling::source::Source;
13
14#[derive(PartialEq, Eq, Clone)]
15pub struct MatZnx<D: Data> {
16 data: D,
17 n: usize,
18 size: usize,
19 rows: usize,
20 cols_in: usize,
21 cols_out: usize,
22}
23
24impl<D: DataRef> fmt::Debug for MatZnx<D> {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 write!(f, "{}", self)
27 }
28}
29
30impl<D: Data> ZnxInfos for MatZnx<D> {
31 fn cols(&self) -> usize {
32 self.cols_in
33 }
34
35 fn rows(&self) -> usize {
36 self.rows
37 }
38
39 fn n(&self) -> usize {
40 self.n
41 }
42
43 fn size(&self) -> usize {
44 self.size
45 }
46}
47
48impl<D: Data> ZnxSliceSize for MatZnx<D> {
49 fn sl(&self) -> usize {
50 self.n() * self.cols_out()
51 }
52}
53
54impl<D: Data> DataView for MatZnx<D> {
55 type D = D;
56 fn data(&self) -> &Self::D {
57 &self.data
58 }
59}
60
61impl<D: Data> DataViewMut for MatZnx<D> {
62 fn data_mut(&mut self) -> &mut Self::D {
63 &mut self.data
64 }
65}
66
67impl<D: DataRef> ZnxView for MatZnx<D> {
68 type Scalar = i64;
69}
70
71impl<D: Data> MatZnx<D> {
72 pub fn cols_in(&self) -> usize {
73 self.cols_in
74 }
75
76 pub fn cols_out(&self) -> usize {
77 self.cols_out
78 }
79}
80
81impl<D: DataRef> MatZnx<D> {
82 pub fn bytes_of(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
83 rows * cols_in * VecZnx::<Vec<u8>>::alloc_bytes::<i64>(n, cols_out, size)
84 }
85}
86
87impl<D: DataRef + From<Vec<u8>>> MatZnx<D> {
88 pub(crate) fn alloc(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
89 let data: Vec<u8> = alloc_aligned(Self::bytes_of(n, rows, cols_in, cols_out, size));
90 Self {
91 data: data.into(),
92 n,
93 size,
94 rows,
95 cols_in,
96 cols_out,
97 }
98 }
99
100 pub(crate) fn from_bytes(
101 n: usize,
102 rows: usize,
103 cols_in: usize,
104 cols_out: usize,
105 size: usize,
106 bytes: impl Into<Vec<u8>>,
107 ) -> Self {
108 let data: Vec<u8> = bytes.into();
109 assert!(data.len() == Self::bytes_of(n, rows, cols_in, cols_out, size));
110 Self {
111 data: data.into(),
112 n,
113 size,
114 rows,
115 cols_in,
116 cols_out,
117 }
118 }
119}
120
121impl<D: DataRef> MatZnx<D> {
122 pub fn at(&self, row: usize, col: usize) -> VecZnx<&[u8]> {
123 #[cfg(debug_assertions)]
124 {
125 assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
126 assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());
127 }
128
129 let self_ref: MatZnx<&[u8]> = self.to_ref();
130 let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes::<i64>(self.n, self.cols_out, self.size);
131 let start: usize = nb_bytes * self.cols() * row + col * nb_bytes;
132 let end: usize = start + nb_bytes;
133
134 VecZnx {
135 data: &self_ref.data[start..end],
136 n: self.n,
137 cols: self.cols_out,
138 size: self.size,
139 max_size: self.size,
140 }
141 }
142}
143
144impl<D: DataMut> MatZnx<D> {
145 pub fn at_mut(&mut self, row: usize, col: usize) -> VecZnx<&mut [u8]> {
146 #[cfg(debug_assertions)]
147 {
148 assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
149 assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());
150 }
151
152 let n: usize = self.n();
153 let cols_out: usize = self.cols_out();
154 let cols_in: usize = self.cols_in();
155 let size: usize = self.size();
156
157 let self_ref: MatZnx<&mut [u8]> = self.to_mut();
158 let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes::<i64>(n, cols_out, size);
159 let start: usize = nb_bytes * cols_in * row + col * nb_bytes;
160 let end: usize = start + nb_bytes;
161
162 VecZnx {
163 data: &mut self_ref.data[start..end],
164 n,
165 cols: cols_out,
166 size,
167 max_size: size,
168 }
169 }
170}
171
172impl<D: DataMut> FillUniform for MatZnx<D> {
173 fn fill_uniform(&mut self, source: &mut Source) {
174 source.fill_bytes(self.data.as_mut());
175 }
176}
177
178pub type MatZnxOwned = MatZnx<Vec<u8>>;
179pub type MatZnxMut<'a> = MatZnx<&'a mut [u8]>;
180pub type MatZnxRef<'a> = MatZnx<&'a [u8]>;
181
182pub trait MatZnxToRef {
183 fn to_ref(&self) -> MatZnx<&[u8]>;
184}
185
186impl<D: DataRef> MatZnxToRef for MatZnx<D> {
187 fn to_ref(&self) -> MatZnx<&[u8]> {
188 MatZnx {
189 data: self.data.as_ref(),
190 n: self.n,
191 rows: self.rows,
192 cols_in: self.cols_in,
193 cols_out: self.cols_out,
194 size: self.size,
195 }
196 }
197}
198
199pub trait MatZnxToMut {
200 fn to_mut(&mut self) -> MatZnx<&mut [u8]>;
201}
202
203impl<D: DataMut> MatZnxToMut for MatZnx<D> {
204 fn to_mut(&mut self) -> MatZnx<&mut [u8]> {
205 MatZnx {
206 data: self.data.as_mut(),
207 n: self.n,
208 rows: self.rows,
209 cols_in: self.cols_in,
210 cols_out: self.cols_out,
211 size: self.size,
212 }
213 }
214}
215
216impl<D: Data> MatZnx<D> {
217 pub(crate) fn from_data(data: D, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
218 Self {
219 data,
220 n,
221 rows,
222 cols_in,
223 cols_out,
224 size,
225 }
226 }
227}
228
229impl<D: DataMut> ReaderFrom for MatZnx<D> {
230 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
231 self.n = reader.read_u64::<LittleEndian>()? as usize;
232 self.size = reader.read_u64::<LittleEndian>()? as usize;
233 self.rows = reader.read_u64::<LittleEndian>()? as usize;
234 self.cols_in = reader.read_u64::<LittleEndian>()? as usize;
235 self.cols_out = reader.read_u64::<LittleEndian>()? as usize;
236 let len: usize = reader.read_u64::<LittleEndian>()? as usize;
237 let buf: &mut [u8] = self.data.as_mut();
238 if buf.len() != len {
239 return Err(std::io::Error::new(
240 std::io::ErrorKind::UnexpectedEof,
241 format!("self.data.len()={} != read len={}", buf.len(), len),
242 ));
243 }
244 reader.read_exact(&mut buf[..len])?;
245 Ok(())
246 }
247}
248
249impl<D: DataRef> WriterTo for MatZnx<D> {
250 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
251 writer.write_u64::<LittleEndian>(self.n as u64)?;
252 writer.write_u64::<LittleEndian>(self.size as u64)?;
253 writer.write_u64::<LittleEndian>(self.rows as u64)?;
254 writer.write_u64::<LittleEndian>(self.cols_in as u64)?;
255 writer.write_u64::<LittleEndian>(self.cols_out as u64)?;
256 let buf: &[u8] = self.data.as_ref();
257 writer.write_u64::<LittleEndian>(buf.len() as u64)?;
258 writer.write_all(buf)?;
259 Ok(())
260 }
261}
262
263impl<D: DataRef> fmt::Display for MatZnx<D> {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 writeln!(
266 f,
267 "MatZnx(n={}, rows={}, cols_in={}, cols_out={}, size={})",
268 self.n, self.rows, self.cols_in, self.cols_out, self.size
269 )?;
270
271 for row_i in 0..self.rows {
272 writeln!(f, "Row {}:", row_i)?;
273 for col_i in 0..self.cols_in {
274 writeln!(f, "cols_in {}:", col_i)?;
275 writeln!(f, "{}:", self.at(row_i, col_i))?;
276 }
277 }
278 Ok(())
279 }
280}
281
282impl<D: DataMut> ZnxZero for MatZnx<D> {
283 fn zero(&mut self) {
284 self.raw_mut().fill(0)
285 }
286
287 fn zero_at(&mut self, i: usize, j: usize) {
288 self.at_mut(i, j).zero();
289 }
290}