arnaucube
arnaucube/poulpyPublic Self-hosted repository
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}