arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/scalar_znx.rs
base2k/src/scalar_znx.rsRaw
  1use crate::ffi::vec_znx;
  2use crate::znx_base::ZnxInfos;
  3use crate::{
  4    Backend, DataView, DataViewMut, Module, VecZnx, VecZnxToMut, VecZnxToRef, ZnxSliceSize, ZnxView, ZnxViewMut, alloc_aligned,
  5};
  6use rand::seq::SliceRandom;
  7use rand_core::RngCore;
  8use rand_distr::{Distribution, weighted::WeightedIndex};
  9use sampling::source::Source;
 10
 11pub struct ScalarZnx<D> {
 12    pub(crate) data: D,
 13    pub(crate) n: usize,
 14    pub(crate) cols: usize,
 15}
 16
 17impl<D> ZnxInfos for ScalarZnx<D> {
 18    fn cols(&self) -> usize {
 19        self.cols
 20    }
 21
 22    fn rows(&self) -> usize {
 23        1
 24    }
 25
 26    fn n(&self) -> usize {
 27        self.n
 28    }
 29
 30    fn size(&self) -> usize {
 31        1
 32    }
 33}
 34
 35impl<D> ZnxSliceSize for ScalarZnx<D> {
 36    fn sl(&self) -> usize {
 37        self.n()
 38    }
 39}
 40
 41impl<D> DataView for ScalarZnx<D> {
 42    type D = D;
 43    fn data(&self) -> &Self::D {
 44        &self.data
 45    }
 46}
 47
 48impl<D> DataViewMut for ScalarZnx<D> {
 49    fn data_mut(&mut self) -> &mut Self::D {
 50        &mut self.data
 51    }
 52}
 53
 54impl<D: AsRef<[u8]>> ZnxView for ScalarZnx<D> {
 55    type Scalar = i64;
 56}
 57
 58impl<D: AsMut<[u8]> + AsRef<[u8]>> ScalarZnx<D> {
 59    pub fn fill_ternary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
 60        let choices: [i64; 3] = [-1, 0, 1];
 61        let weights: [f64; 3] = [prob / 2.0, 1.0 - prob, prob / 2.0];
 62        let dist: WeightedIndex<f64> = WeightedIndex::new(&weights).unwrap();
 63        self.at_mut(col, 0)
 64            .iter_mut()
 65            .for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
 66    }
 67
 68    pub fn fill_ternary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
 69        assert!(hw <= self.n());
 70        self.at_mut(col, 0)[..hw]
 71            .iter_mut()
 72            .for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1);
 73        self.at_mut(col, 0).shuffle(source);
 74    }
 75}
 76
 77impl<D: From<Vec<u8>>> ScalarZnx<D> {
 78    pub(crate) fn bytes_of<S: Sized>(n: usize, cols: usize) -> usize {
 79        n * cols * size_of::<S>()
 80    }
 81
 82    pub(crate) fn new<S: Sized>(n: usize, cols: usize) -> Self {
 83        let data = alloc_aligned::<u8>(Self::bytes_of::<S>(n, cols));
 84        Self {
 85            data: data.into(),
 86            n,
 87            cols,
 88        }
 89    }
 90
 91    pub(crate) fn new_from_bytes<S: Sized>(n: usize, cols: usize, bytes: impl Into<Vec<u8>>) -> Self {
 92        let data: Vec<u8> = bytes.into();
 93        assert!(data.len() == Self::bytes_of::<S>(n, cols));
 94        Self {
 95            data: data.into(),
 96            n,
 97            cols,
 98        }
 99    }
100}
101
102pub type ScalarZnxOwned = ScalarZnx<Vec<u8>>;
103
104pub(crate) fn bytes_of_scalar_znx<B: Backend>(module: &Module<B>, cols: usize) -> usize {
105    ScalarZnxOwned::bytes_of::<i64>(module.n(), cols)
106}
107
108pub trait ScalarZnxAlloc {
109    fn bytes_of_scalar_znx(&self, cols: usize) -> usize;
110    fn new_scalar_znx(&self, cols: usize) -> ScalarZnxOwned;
111    fn new_scalar_znx_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarZnxOwned;
112}
113
114impl<B: Backend> ScalarZnxAlloc for Module<B> {
115    fn bytes_of_scalar_znx(&self, cols: usize) -> usize {
116        ScalarZnxOwned::bytes_of::<i64>(self.n(), cols)
117    }
118    fn new_scalar_znx(&self, cols: usize) -> ScalarZnxOwned {
119        ScalarZnxOwned::new::<i64>(self.n(), cols)
120    }
121    fn new_scalar_znx_from_bytes(&self, cols: usize, bytes: Vec<u8>) -> ScalarZnxOwned {
122        ScalarZnxOwned::new_from_bytes::<i64>(self.n(), cols, bytes)
123    }
124}
125
126pub trait ScalarZnxOps {
127    fn scalar_znx_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
128    where
129        R: ScalarZnxToMut,
130        A: ScalarZnxToRef;
131
132    /// Applies the automorphism X^i -> X^ik on the selected column of `a`.
133    fn scalar_znx_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
134    where
135        A: ScalarZnxToMut;
136}
137
138impl<B: Backend> ScalarZnxOps for Module<B> {
139    fn scalar_znx_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
140    where
141        R: ScalarZnxToMut,
142        A: ScalarZnxToRef,
143    {
144        let a: ScalarZnx<&[u8]> = a.to_ref();
145        let mut res: ScalarZnx<&mut [u8]> = res.to_mut();
146        #[cfg(debug_assertions)]
147        {
148            assert_eq!(a.n(), self.n());
149            assert_eq!(res.n(), self.n());
150        }
151        unsafe {
152            vec_znx::vec_znx_automorphism(
153                self.ptr,
154                k,
155                res.at_mut_ptr(res_col, 0),
156                res.size() as u64,
157                res.sl() as u64,
158                a.at_ptr(a_col, 0),
159                a.size() as u64,
160                a.sl() as u64,
161            )
162        }
163    }
164
165    fn scalar_znx_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
166    where
167        A: ScalarZnxToMut,
168    {
169        let mut a: ScalarZnx<&mut [u8]> = a.to_mut();
170        #[cfg(debug_assertions)]
171        {
172            assert_eq!(a.n(), self.n());
173        }
174        unsafe {
175            vec_znx::vec_znx_automorphism(
176                self.ptr,
177                k,
178                a.at_mut_ptr(a_col, 0),
179                a.size() as u64,
180                a.sl() as u64,
181                a.at_ptr(a_col, 0),
182                a.size() as u64,
183                a.sl() as u64,
184            )
185        }
186    }
187}
188
189impl<D> ScalarZnx<D> {
190    pub(crate) fn from_data(data: D, n: usize, cols: usize) -> Self {
191        Self { data, n, cols }
192    }
193}
194
195pub trait ScalarZnxToRef {
196    fn to_ref(&self) -> ScalarZnx<&[u8]>;
197}
198
199pub trait ScalarZnxToMut {
200    fn to_mut(&mut self) -> ScalarZnx<&mut [u8]>;
201}
202
203impl ScalarZnxToMut for ScalarZnx<Vec<u8>> {
204    fn to_mut(&mut self) -> ScalarZnx<&mut [u8]> {
205        ScalarZnx {
206            data: self.data.as_mut_slice(),
207            n: self.n,
208            cols: self.cols,
209        }
210    }
211}
212
213impl VecZnxToMut for ScalarZnx<Vec<u8>> {
214    fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
215        VecZnx {
216            data: self.data.as_mut_slice(),
217            n: self.n,
218            cols: self.cols,
219            size: 1,
220        }
221    }
222}
223
224impl ScalarZnxToRef for ScalarZnx<Vec<u8>> {
225    fn to_ref(&self) -> ScalarZnx<&[u8]> {
226        ScalarZnx {
227            data: self.data.as_slice(),
228            n: self.n,
229            cols: self.cols,
230        }
231    }
232}
233
234impl VecZnxToRef for ScalarZnx<Vec<u8>> {
235    fn to_ref(&self) -> VecZnx<&[u8]> {
236        VecZnx {
237            data: self.data.as_slice(),
238            n: self.n,
239            cols: self.cols,
240            size: 1,
241        }
242    }
243}
244
245impl ScalarZnxToMut for ScalarZnx<&mut [u8]> {
246    fn to_mut(&mut self) -> ScalarZnx<&mut [u8]> {
247        ScalarZnx {
248            data: self.data,
249            n: self.n,
250            cols: self.cols,
251        }
252    }
253}
254
255impl VecZnxToMut for ScalarZnx<&mut [u8]> {
256    fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
257        VecZnx {
258            data: self.data,
259            n: self.n,
260            cols: self.cols,
261            size: 1,
262        }
263    }
264}
265
266impl ScalarZnxToRef for ScalarZnx<&mut [u8]> {
267    fn to_ref(&self) -> ScalarZnx<&[u8]> {
268        ScalarZnx {
269            data: self.data,
270            n: self.n,
271            cols: self.cols,
272        }
273    }
274}
275
276impl VecZnxToRef for ScalarZnx<&mut [u8]> {
277    fn to_ref(&self) -> VecZnx<&[u8]> {
278        VecZnx {
279            data: self.data,
280            n: self.n,
281            cols: self.cols,
282            size: 1,
283        }
284    }
285}
286
287impl ScalarZnxToRef for ScalarZnx<&[u8]> {
288    fn to_ref(&self) -> ScalarZnx<&[u8]> {
289        ScalarZnx {
290            data: self.data,
291            n: self.n,
292            cols: self.cols,
293        }
294    }
295}
296
297impl VecZnxToRef for ScalarZnx<&[u8]> {
298    fn to_ref(&self) -> VecZnx<&[u8]> {
299        VecZnx {
300            data: self.data,
301            n: self.n,
302            cols: self.cols,
303            size: 1,
304        }
305    }
306}