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, Reset, 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 MatZnx<Vec<u8>> {
82 pub fn alloc_bytes(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
83 rows * cols_in * VecZnx::<Vec<u8>>::alloc_bytes(n, cols_out, size)
84 }
85
86 pub fn alloc(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
87 let data: Vec<u8> = alloc_aligned(Self::alloc_bytes(n, rows, cols_in, cols_out, size));
88 Self {
89 data: data.into(),
90 n,
91 size,
92 rows,
93 cols_in,
94 cols_out,
95 }
96 }
97
98 pub fn from_bytes(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self {
99 let data: Vec<u8> = bytes.into();
100 assert!(data.len() == Self::alloc_bytes(n, rows, cols_in, cols_out, size));
101 Self {
102 data: data.into(),
103 n,
104 size,
105 rows,
106 cols_in,
107 cols_out,
108 }
109 }
110}
111
112impl<D: DataRef> MatZnx<D> {
113 pub fn at(&self, row: usize, col: usize) -> VecZnx<&[u8]> {
114 #[cfg(debug_assertions)]
115 {
116 assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
117 assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());
118 }
119
120 let self_ref: MatZnx<&[u8]> = self.to_ref();
121 let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes(self.n, self.cols_out, self.size);
122 let start: usize = nb_bytes * self.cols() * row + col * nb_bytes;
123 let end: usize = start + nb_bytes;
124
125 VecZnx {
126 data: &self_ref.data[start..end],
127 n: self.n,
128 cols: self.cols_out,
129 size: self.size,
130 max_size: self.size,
131 }
132 }
133}
134
135impl<D: DataMut> MatZnx<D> {
136 pub fn at_mut(&mut self, row: usize, col: usize) -> VecZnx<&mut [u8]> {
137 #[cfg(debug_assertions)]
138 {
139 assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
140 assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());
141 }
142
143 let n: usize = self.n();
144 let cols_out: usize = self.cols_out();
145 let cols_in: usize = self.cols_in();
146 let size: usize = self.size();
147
148 let self_ref: MatZnx<&mut [u8]> = self.to_mut();
149 let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes(n, cols_out, size);
150 let start: usize = nb_bytes * cols_in * row + col * nb_bytes;
151 let end: usize = start + nb_bytes;
152
153 VecZnx {
154 data: &mut self_ref.data[start..end],
155 n,
156 cols: cols_out,
157 size,
158 max_size: size,
159 }
160 }
161}
162
163impl<D: DataMut> FillUniform for MatZnx<D> {
164 fn fill_uniform(&mut self, source: &mut Source) {
165 source.fill_bytes(self.data.as_mut());
166 }
167}
168
169impl<D: DataMut> Reset for MatZnx<D> {
170 fn reset(&mut self) {
171 self.zero();
172 self.n = 0;
173 self.size = 0;
174 self.rows = 0;
175 self.cols_in = 0;
176 self.cols_out = 0;
177 }
178}
179
180pub type MatZnxOwned = MatZnx<Vec<u8>>;
181pub type MatZnxMut<'a> = MatZnx<&'a mut [u8]>;
182pub type MatZnxRef<'a> = MatZnx<&'a [u8]>;
183
184pub trait MatZnxToRef {
185 fn to_ref(&self) -> MatZnx<&[u8]>;
186}
187
188impl<D: DataRef> MatZnxToRef for MatZnx<D> {
189 fn to_ref(&self) -> MatZnx<&[u8]> {
190 MatZnx {
191 data: self.data.as_ref(),
192 n: self.n,
193 rows: self.rows,
194 cols_in: self.cols_in,
195 cols_out: self.cols_out,
196 size: self.size,
197 }
198 }
199}
200
201pub trait MatZnxToMut {
202 fn to_mut(&mut self) -> MatZnx<&mut [u8]>;
203}
204
205impl<D: DataMut> MatZnxToMut for MatZnx<D> {
206 fn to_mut(&mut self) -> MatZnx<&mut [u8]> {
207 MatZnx {
208 data: self.data.as_mut(),
209 n: self.n,
210 rows: self.rows,
211 cols_in: self.cols_in,
212 cols_out: self.cols_out,
213 size: self.size,
214 }
215 }
216}
217
218impl<D: Data> MatZnx<D> {
219 pub(crate) fn from_data(data: D, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
220 Self {
221 data,
222 n,
223 rows,
224 cols_in,
225 cols_out,
226 size,
227 }
228 }
229}
230
231impl<D: DataMut> ReaderFrom for MatZnx<D> {
232 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
233 self.n = reader.read_u64::<LittleEndian>()? as usize;
234 self.size = reader.read_u64::<LittleEndian>()? as usize;
235 self.rows = reader.read_u64::<LittleEndian>()? as usize;
236 self.cols_in = reader.read_u64::<LittleEndian>()? as usize;
237 self.cols_out = reader.read_u64::<LittleEndian>()? as usize;
238 let len: usize = reader.read_u64::<LittleEndian>()? as usize;
239 let buf: &mut [u8] = self.data.as_mut();
240 if buf.len() != len {
241 return Err(std::io::Error::new(
242 std::io::ErrorKind::UnexpectedEof,
243 format!("self.data.len()={} != read len={}", buf.len(), len),
244 ));
245 }
246 reader.read_exact(&mut buf[..len])?;
247 Ok(())
248 }
249}
250
251impl<D: DataRef> WriterTo for MatZnx<D> {
252 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
253 writer.write_u64::<LittleEndian>(self.n as u64)?;
254 writer.write_u64::<LittleEndian>(self.size as u64)?;
255 writer.write_u64::<LittleEndian>(self.rows as u64)?;
256 writer.write_u64::<LittleEndian>(self.cols_in as u64)?;
257 writer.write_u64::<LittleEndian>(self.cols_out as u64)?;
258 let buf: &[u8] = self.data.as_ref();
259 writer.write_u64::<LittleEndian>(buf.len() as u64)?;
260 writer.write_all(buf)?;
261 Ok(())
262 }
263}
264
265impl<D: DataRef> fmt::Display for MatZnx<D> {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 writeln!(
268 f,
269 "MatZnx(n={}, rows={}, cols_in={}, cols_out={}, size={})",
270 self.n, self.rows, self.cols_in, self.cols_out, self.size
271 )?;
272
273 for row_i in 0..self.rows {
274 writeln!(f, "Row {}:", row_i)?;
275 for col_i in 0..self.cols_in {
276 writeln!(f, "cols_in {}:", col_i)?;
277 writeln!(f, "{}:", self.at(row_i, col_i))?;
278 }
279 }
280 Ok(())
281 }
282}
283
284impl<D: DataMut> ZnxZero for MatZnx<D> {
285 fn zero(&mut self) {
286 self.raw_mut().fill(0)
287 }
288
289 fn zero_at(&mut self, i: usize, j: usize) {
290 self.at_mut(i, j).zero();
291 }
292}