poulpy/base2k/src/scalar_znx.rs
base2k/src/scalar_znx.rsRaw
1use crate::znx_base::ZnxInfos;
2use crate::{Backend, DataView, DataViewMut, Module, ZnxSliceSize, ZnxView, ZnxViewMut, alloc_aligned};
3use rand::seq::SliceRandom;
4use rand_core::RngCore;
5use rand_distr::{Distribution, weighted::WeightedIndex};
6use sampling::source::Source;
7
8pub struct Scalar<D> {
9 data: D,
10 n: usize,
11 cols: usize,
12}
13
14impl<D> ZnxInfos for Scalar<D> {
15 fn cols(&self) -> usize {
16 self.cols
17 }
18
19 fn rows(&self) -> usize {
20 1
21 }
22
23 fn n(&self) -> usize {
24 self.n
25 }
26
27 fn size(&self) -> usize {
28 1
29 }
30}
31
32impl<D> ZnxSliceSize for Scalar<D> {
33 fn sl(&self) -> usize {
34 self.n()
35 }
36}
37
38impl<D> DataView for Scalar<D> {
39 type D = D;
40 fn data(&self) -> &Self::D {
41 &self.data
42 }
43}
44
45impl<D> DataViewMut for Scalar<D> {
46 fn data_mut(&mut self) -> &mut Self::D {
47 &mut self.data
48 }
49}
50
51impl<D: AsRef<[u8]>> ZnxView for Scalar<D> {
52 type Scalar = i64;
53}
54
55impl<D: AsMut<[u8]> + AsRef<[u8]>> Scalar<D> {
56 pub fn fill_ternary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
57 let choices: [i64; 3] = [-1, 0, 1];
58 let weights: [f64; 3] = [prob / 2.0, 1.0 - prob, prob / 2.0];
59 let dist: WeightedIndex<f64> = WeightedIndex::new(&weights).unwrap();
60 self.at_mut(col, 0)
61 .iter_mut()
62 .for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
63 }
64
65 pub fn fill_ternary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
66 assert!(hw <= self.n());
67 self.at_mut(col, 0)[..hw]
68 .iter_mut()
69 .for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1);
70 self.at_mut(col, 0).shuffle(source);
71 }
72}
73
74impl<D: From<Vec<u8>>> Scalar<D> {
75 pub(crate) fn bytes_of<S: Sized>(n: usize, cols: usize) -> usize {
76 n * cols * size_of::<S>()
77 }
78
79 pub(crate) fn new<S: Sized>(n: usize, cols: usize) -> Self {
80 let data = alloc_aligned::<u8>(Self::bytes_of::<S>(n, cols));
81 Self {
82 data: data.into(),
83 n,
84 cols,
85 }
86 }
87
88 pub(crate) fn new_from_bytes<S: Sized>(n: usize, cols: usize, bytes: impl Into<Vec<u8>>) -> Self {
89 let data: Vec<u8> = bytes.into();
90 assert!(data.len() == Self::bytes_of::<S>(n, cols));
91 Self {
92 data: data.into(),
93 n,
94 cols,
95 }
96 }
97}
98
99pub type ScalarOwned = Scalar<Vec<u8>>;
100
101pub trait ScalarAlloc {
102 fn bytes_of_scalar(&self, cols: usize) -> usize;
103 fn new_scalar(&self, cols: usize) -> ScalarOwned;
104 fn new_scalar_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarOwned;
105}
106
107impl<B: Backend> ScalarAlloc for Module<B> {
108 fn bytes_of_scalar(&self, cols: usize) -> usize {
109 ScalarOwned::bytes_of::<i64>(self.n(), cols)
110 }
111 fn new_scalar(&self, cols: usize) -> ScalarOwned {
112 ScalarOwned::new::<i64>(self.n(), cols)
113 }
114 fn new_scalar_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarOwned {
115 ScalarOwned::new_from_bytes::<i64>(self.n(), cols, bytes)
116 }
117}
118
119pub trait ScalarToRef {
120 fn to_ref(&self) -> Scalar<&[u8]>;
121}
122
123pub trait ScalarToMut {
124 fn to_mut(&mut self) -> Scalar<&mut [u8]>;
125}
126
127impl ScalarToMut for Scalar<Vec<u8>> {
128 fn to_mut(&mut self) -> Scalar<&mut [u8]> {
129 Scalar {
130 data: self.data.as_mut_slice(),
131 n: self.n,
132 cols: self.cols,
133 }
134 }
135}
136
137impl ScalarToRef for Scalar<Vec<u8>> {
138 fn to_ref(&self) -> Scalar<&[u8]> {
139 Scalar {
140 data: self.data.as_slice(),
141 n: self.n,
142 cols: self.cols,
143 }
144 }
145}
146
147impl ScalarToMut for Scalar<&mut [u8]> {
148 fn to_mut(&mut self) -> Scalar<&mut [u8]> {
149 Scalar {
150 data: self.data,
151 n: self.n,
152 cols: self.cols,
153 }
154 }
155}
156
157impl ScalarToRef for Scalar<&mut [u8]> {
158 fn to_ref(&self) -> Scalar<&[u8]> {
159 Scalar {
160 data: self.data,
161 n: self.n,
162 cols: self.cols,
163 }
164 }
165}
166
167impl ScalarToRef for Scalar<&[u8]> {
168 fn to_ref(&self) -> Scalar<&[u8]> {
169 Scalar {
170 data: self.data,
171 n: self.n,
172 cols: self.cols,
173 }
174 }
175}