poulpy/backend/src/hal/layouts/vec_znx.rs
backend/src/hal/layouts/vec_znx.rsRaw
1use std::fmt;
2
3use crate::{
4 alloc_aligned,
5 hal::{
6 api::{DataView, DataViewMut, FillUniform, Reset, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
7 layouts::{Data, DataMut, DataRef, ReaderFrom, WriterTo},
8 },
9};
10
11#[derive(PartialEq, Eq, Clone)]
12pub struct VecZnx<D: Data> {
13 pub(crate) data: D,
14 pub(crate) n: usize,
15 pub(crate) cols: usize,
16 pub(crate) size: usize,
17 pub(crate) max_size: usize,
18}
19
20impl<D: DataRef> fmt::Debug for VecZnx<D> {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 write!(f, "{}", self)
23 }
24}
25
26impl<D: Data> ZnxInfos for VecZnx<D> {
27 fn cols(&self) -> usize {
28 self.cols
29 }
30
31 fn rows(&self) -> usize {
32 1
33 }
34
35 fn n(&self) -> usize {
36 self.n
37 }
38
39 fn size(&self) -> usize {
40 self.size
41 }
42}
43
44impl<D: Data> ZnxSliceSize for VecZnx<D> {
45 fn sl(&self) -> usize {
46 self.n() * self.cols()
47 }
48}
49
50impl<D: Data> DataView for VecZnx<D> {
51 type D = D;
52 fn data(&self) -> &Self::D {
53 &self.data
54 }
55}
56
57impl<D: Data> DataViewMut for VecZnx<D> {
58 fn data_mut(&mut self) -> &mut Self::D {
59 &mut self.data
60 }
61}
62
63impl<D: DataRef> ZnxView for VecZnx<D> {
64 type Scalar = i64;
65}
66
67impl VecZnx<Vec<u8>> {
68 pub fn rsh_scratch_space(n: usize) -> usize {
69 n * std::mem::size_of::<i64>()
70 }
71}
72
73impl<D: DataMut> ZnxZero for VecZnx<D> {
74 fn zero(&mut self) {
75 self.raw_mut().fill(0)
76 }
77 fn zero_at(&mut self, i: usize, j: usize) {
78 self.at_mut(i, j).fill(0);
79 }
80}
81
82impl VecZnx<Vec<u8>> {
83 pub fn alloc_bytes(n: usize, cols: usize, size: usize) -> usize {
84 n * cols * size * size_of::<i64>()
85 }
86
87 pub fn alloc(n: usize, cols: usize, size: usize) -> Self {
88 let data: Vec<u8> = alloc_aligned::<u8>(Self::alloc_bytes(n, cols, size));
89 Self {
90 data: data.into(),
91 n,
92 cols,
93 size,
94 max_size: size,
95 }
96 }
97
98 pub fn from_bytes<Scalar: Sized>(n: usize, cols: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self {
99 let data: Vec<u8> = bytes.into();
100 assert!(data.len() == Self::alloc_bytes(n, cols, size));
101 Self {
102 data: data.into(),
103 n,
104 cols,
105 size,
106 max_size: size,
107 }
108 }
109}
110
111impl<D: Data> VecZnx<D> {
112 pub fn from_data(data: D, n: usize, cols: usize, size: usize) -> Self {
113 Self {
114 data,
115 n,
116 cols,
117 size,
118 max_size: size,
119 }
120 }
121}
122
123impl<D: DataRef> fmt::Display for VecZnx<D> {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 writeln!(
126 f,
127 "VecZnx(n={}, cols={}, size={})",
128 self.n, self.cols, self.size
129 )?;
130
131 for col in 0..self.cols {
132 writeln!(f, "Column {}:", col)?;
133 for size in 0..self.size {
134 let coeffs = self.at(col, size);
135 write!(f, " Size {}: [", size)?;
136
137 let max_show = 100;
138 let show_count = coeffs.len().min(max_show);
139
140 for (i, &coeff) in coeffs.iter().take(show_count).enumerate() {
141 if i > 0 {
142 write!(f, ", ")?;
143 }
144 write!(f, "{}", coeff)?;
145 }
146
147 if coeffs.len() > max_show {
148 write!(f, ", ... ({} more)", coeffs.len() - max_show)?;
149 }
150
151 writeln!(f, "]")?;
152 }
153 }
154 Ok(())
155 }
156}
157
158impl<D: DataMut> FillUniform for VecZnx<D> {
159 fn fill_uniform(&mut self, source: &mut Source) {
160 source.fill_bytes(self.data.as_mut());
161 }
162}
163
164impl<D: DataMut> Reset for VecZnx<D> {
165 fn reset(&mut self) {
166 self.zero();
167 self.n = 0;
168 self.cols = 0;
169 self.size = 0;
170 self.max_size = 0;
171 }
172}
173
174pub type VecZnxOwned = VecZnx<Vec<u8>>;
175pub type VecZnxMut<'a> = VecZnx<&'a mut [u8]>;
176pub type VecZnxRef<'a> = VecZnx<&'a [u8]>;
177
178pub trait VecZnxToRef {
179 fn to_ref(&self) -> VecZnx<&[u8]>;
180}
181
182impl<D: DataRef> VecZnxToRef for VecZnx<D> {
183 fn to_ref(&self) -> VecZnx<&[u8]> {
184 VecZnx {
185 data: self.data.as_ref(),
186 n: self.n,
187 cols: self.cols,
188 size: self.size,
189 max_size: self.max_size,
190 }
191 }
192}
193
194pub trait VecZnxToMut {
195 fn to_mut(&mut self) -> VecZnx<&mut [u8]>;
196}
197
198impl<D: DataMut> VecZnxToMut for VecZnx<D> {
199 fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
200 VecZnx {
201 data: self.data.as_mut(),
202 n: self.n,
203 cols: self.cols,
204 size: self.size,
205 max_size: self.max_size,
206 }
207 }
208}
209
210impl<D: DataRef> VecZnx<D> {
211 pub fn clone(&self) -> VecZnx<Vec<u8>> {
212 let self_ref: VecZnx<&[u8]> = self.to_ref();
213 VecZnx {
214 data: self_ref.data.to_vec(),
215 n: self_ref.n,
216 cols: self_ref.cols,
217 size: self_ref.size,
218 max_size: self_ref.max_size,
219 }
220 }
221}
222
223use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
224use rand::RngCore;
225use sampling::source::Source;
226
227impl<D: DataMut> ReaderFrom for VecZnx<D> {
228 fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
229 self.n = reader.read_u64::<LittleEndian>()? as usize;
230 self.cols = reader.read_u64::<LittleEndian>()? as usize;
231 self.size = reader.read_u64::<LittleEndian>()? as usize;
232 self.max_size = reader.read_u64::<LittleEndian>()? as usize;
233 let len: usize = reader.read_u64::<LittleEndian>()? as usize;
234 let buf: &mut [u8] = self.data.as_mut();
235 if buf.len() != len {
236 return Err(std::io::Error::new(
237 std::io::ErrorKind::UnexpectedEof,
238 format!("self.data.len()={} != read len={}", buf.len(), len),
239 ));
240 }
241 reader.read_exact(&mut buf[..len])?;
242 Ok(())
243 }
244}
245
246impl<D: DataRef> WriterTo for VecZnx<D> {
247 fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
248 writer.write_u64::<LittleEndian>(self.n as u64)?;
249 writer.write_u64::<LittleEndian>(self.cols as u64)?;
250 writer.write_u64::<LittleEndian>(self.size as u64)?;
251 writer.write_u64::<LittleEndian>(self.max_size as u64)?;
252 let buf: &[u8] = self.data.as_ref();
253 writer.write_u64::<LittleEndian>(buf.len() as u64)?;
254 writer.write_all(buf)?;
255 Ok(())
256 }
257}