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