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