poulpy/base2k/src/scalar_znx.rs
base2k/src/scalar_znx.rsRaw
1use crate::znx_base::ZnxInfos;
2use crate::{
3 Backend, DataView, DataViewMut, Module, VecZnx, VecZnxToMut, VecZnxToRef, ZnxSliceSize, ZnxView, ZnxViewMut, alloc_aligned,
4};
5use rand::seq::SliceRandom;
6use rand_core::RngCore;
7use rand_distr::{Distribution, weighted::WeightedIndex};
8use sampling::source::Source;
9
10pub struct ScalarZnx<D> {
11 data: D,
12 n: usize,
13 cols: usize,
14}
15
16impl<D> ZnxInfos for ScalarZnx<D> {
17 fn cols(&self) -> usize {
18 self.cols
19 }
20
21 fn rows(&self) -> usize {
22 1
23 }
24
25 fn n(&self) -> usize {
26 self.n
27 }
28
29 fn size(&self) -> usize {
30 1
31 }
32}
33
34impl<D> ZnxSliceSize for ScalarZnx<D> {
35 fn sl(&self) -> usize {
36 self.n()
37 }
38}
39
40impl<D> DataView for ScalarZnx<D> {
41 type D = D;
42 fn data(&self) -> &Self::D {
43 &self.data
44 }
45}
46
47impl<D> DataViewMut for ScalarZnx<D> {
48 fn data_mut(&mut self) -> &mut Self::D {
49 &mut self.data
50 }
51}
52
53impl<D: AsRef<[u8]>> ZnxView for ScalarZnx<D> {
54 type Scalar = i64;
55}
56
57impl<D: AsMut<[u8]> + AsRef<[u8]>> ScalarZnx<D> {
58 pub fn fill_ternary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
59 let choices: [i64; 3] = [-1, 0, 1];
60 let weights: [f64; 3] = [prob / 2.0, 1.0 - prob, prob / 2.0];
61 let dist: WeightedIndex<f64> = WeightedIndex::new(&weights).unwrap();
62 self.at_mut(col, 0)
63 .iter_mut()
64 .for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
65 }
66
67 pub fn fill_ternary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
68 assert!(hw <= self.n());
69 self.at_mut(col, 0)[..hw]
70 .iter_mut()
71 .for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1);
72 self.at_mut(col, 0).shuffle(source);
73 }
74}
75
76impl<D: From<Vec<u8>>> ScalarZnx<D> {
77 pub(crate) fn bytes_of<S: Sized>(n: usize, cols: usize) -> usize {
78 n * cols * size_of::<S>()
79 }
80
81 pub(crate) fn new<S: Sized>(n: usize, cols: usize) -> Self {
82 let data = alloc_aligned::<u8>(Self::bytes_of::<S>(n, cols));
83 Self {
84 data: data.into(),
85 n,
86 cols,
87 }
88 }
89
90 pub(crate) fn new_from_bytes<S: Sized>(n: usize, cols: usize, bytes: impl Into<Vec<u8>>) -> Self {
91 let data: Vec<u8> = bytes.into();
92 assert!(data.len() == Self::bytes_of::<S>(n, cols));
93 Self {
94 data: data.into(),
95 n,
96 cols,
97 }
98 }
99}
100
101pub type ScalarZnxOwned = ScalarZnx<Vec<u8>>;
102
103pub(crate) fn bytes_of_scalar_znx<B: Backend>(module: &Module<B>, cols: usize) -> usize {
104 ScalarZnxOwned::bytes_of::<i64>(module.n(), cols)
105}
106
107pub trait ScalarZnxAlloc {
108 fn bytes_of_scalar_znx(&self, cols: usize) -> usize;
109 fn new_scalar_znx(&self, cols: usize) -> ScalarZnxOwned;
110 fn new_scalar_znx_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarZnxOwned;
111}
112
113impl<B: Backend> ScalarZnxAlloc for Module<B> {
114 fn bytes_of_scalar_znx(&self, cols: usize) -> usize {
115 ScalarZnxOwned::bytes_of::<i64>(self.n(), cols)
116 }
117 fn new_scalar_znx(&self, cols: usize) -> ScalarZnxOwned {
118 ScalarZnxOwned::new::<i64>(self.n(), cols)
119 }
120 fn new_scalar_znx_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarZnxOwned {
121 ScalarZnxOwned::new_from_bytes::<i64>(self.n(), cols, bytes)
122 }
123}
124
125impl<D> ScalarZnx<D> {
126 pub(crate) fn from_data(data: D, n: usize, cols: usize) -> Self {
127 Self { data, n, cols }
128 }
129}
130
131pub trait ScalarZnxToRef {
132 fn to_ref(&self) -> ScalarZnx<&[u8]>;
133}
134
135pub trait ScalarZnxToMut {
136 fn to_mut(&mut self) -> ScalarZnx<&mut [u8]>;
137}
138
139impl ScalarZnxToMut for ScalarZnx<Vec<u8>> {
140 fn to_mut(&mut self) -> ScalarZnx<&mut [u8]> {
141 ScalarZnx {
142 data: self.data.as_mut_slice(),
143 n: self.n,
144 cols: self.cols,
145 }
146 }
147}
148
149impl VecZnxToMut for ScalarZnx<Vec<u8>> {
150 fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
151 VecZnx {
152 data: self.data.as_mut_slice(),
153 n: self.n,
154 cols: self.cols,
155 size: 1,
156 }
157 }
158}
159
160impl ScalarZnxToRef for ScalarZnx<Vec<u8>> {
161 fn to_ref(&self) -> ScalarZnx<&[u8]> {
162 ScalarZnx {
163 data: self.data.as_slice(),
164 n: self.n,
165 cols: self.cols,
166 }
167 }
168}
169
170impl VecZnxToRef for ScalarZnx<Vec<u8>> {
171 fn to_ref(&self) -> VecZnx<&[u8]> {
172 VecZnx {
173 data: self.data.as_slice(),
174 n: self.n,
175 cols: self.cols,
176 size: 1,
177 }
178 }
179}
180
181impl ScalarZnxToMut for ScalarZnx<&mut [u8]> {
182 fn to_mut(&mut self) -> ScalarZnx<&mut [u8]> {
183 ScalarZnx {
184 data: self.data,
185 n: self.n,
186 cols: self.cols,
187 }
188 }
189}
190
191impl VecZnxToMut for ScalarZnx<&mut [u8]> {
192 fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
193 VecZnx {
194 data: self.data,
195 n: self.n,
196 cols: self.cols,
197 size: 1,
198 }
199 }
200}
201
202impl ScalarZnxToRef for ScalarZnx<&mut [u8]> {
203 fn to_ref(&self) -> ScalarZnx<&[u8]> {
204 ScalarZnx {
205 data: self.data,
206 n: self.n,
207 cols: self.cols,
208 }
209 }
210}
211
212impl VecZnxToRef for ScalarZnx<&mut [u8]> {
213 fn to_ref(&self) -> VecZnx<&[u8]> {
214 VecZnx {
215 data: self.data,
216 n: self.n,
217 cols: self.cols,
218 size: 1,
219 }
220 }
221}
222
223impl ScalarZnxToRef for ScalarZnx<&[u8]> {
224 fn to_ref(&self) -> ScalarZnx<&[u8]> {
225 ScalarZnx {
226 data: self.data,
227 n: self.n,
228 cols: self.cols,
229 }
230 }
231}
232
233impl VecZnxToRef for ScalarZnx<&[u8]> {
234 fn to_ref(&self) -> VecZnx<&[u8]> {
235 VecZnx {
236 data: self.data,
237 n: self.n,
238 cols: self.cols,
239 size: 1,
240 }
241 }
242}