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