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, 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}