poulpy/math/src/ring/impl_u64/sampling.rs
math/src/ring/impl_u64/sampling.rsRaw
1use crate::modulus::WordOps;
2use crate::poly::{Poly, PolyRNS};
3use crate::ring::{Ring, RingRNS};
4use num::ToPrimitive;
5use rand_distr::{Distribution, Normal};
6use sampling::source::Source;
7
8impl Ring<u64> {
9 pub fn fill_uniform(&self, source: &mut Source, a: &mut Poly<u64>) {
10 let max: u64 = self.modulus.q;
11 let mask: u64 = max.mask();
12 a.0.iter_mut()
13 .for_each(|a| *a = source.next_u64n(max, mask));
14 }
15
16 pub fn fill_dist_f64<T: Distribution<f64>>(
17 &self,
18 source: &mut Source,
19 dist: T,
20 bound: f64,
21 a: &mut Poly<u64>,
22 ) {
23 let max: u64 = self.modulus.q;
24 a.0.iter_mut().for_each(|a| {
25 let mut dist_f64: f64 = dist.sample(source);
26
27 while dist_f64.abs() > bound {
28 dist_f64 = dist.sample(source)
29 }
30
31 let dist_u64: u64 = (dist_f64 + 0.5).abs().to_u64().unwrap();
32 let sign: u64 = dist_f64.to_bits() >> 63;
33
34 *a = (dist_u64 * sign) | (max - dist_u64) * (sign ^ 1)
35 });
36 }
37}
38
39impl RingRNS<u64> {
40 pub fn fill_uniform(&self, source: &mut Source, a: &mut PolyRNS<u64>) {
41 self.0
42 .iter()
43 .enumerate()
44 .for_each(|(i, r)| r.fill_uniform(source, a.at_mut(i)));
45 }
46
47 pub fn fill_dist_f64<T: Distribution<f64>>(
48 &self,
49 source: &mut Source,
50 dist: T,
51 bound: f64,
52 a: &mut PolyRNS<u64>,
53 ) {
54 (0..a.n()).for_each(|j| {
55 let mut dist_f64: f64 = dist.sample(source);
56
57 while dist_f64.abs() > bound {
58 dist_f64 = dist.sample(source)
59 }
60
61 let dist_u64: u64 = (dist_f64 + 0.5).abs().to_u64().unwrap();
62 let sign: u64 = dist_f64.to_bits() >> 63;
63
64 self.0.iter().enumerate().for_each(|(i, r)| {
65 a.at_mut(i).0[j] = (dist_u64 * sign) | (r.modulus.q - dist_u64) * (sign ^ 1);
66 })
67 })
68 }
69}