arnaucube
arnaucube/poulpyPublic Self-hosted repository
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    pub fn fill_normal(&self, source: &mut Source, sigma: f64, bound: f64, a: &mut Poly<u64>) {
39        self.fill_dist_f64(source, Normal::new(0.0, sigma).unwrap(), bound, a);
40    }
41}
42
43impl RingRNS<u64> {
44    pub fn fill_uniform(&self, source: &mut Source, a: &mut PolyRNS<u64>) {
45        self.0
46            .iter()
47            .enumerate()
48            .for_each(|(i, r)| r.fill_uniform(source, a.at_mut(i)));
49    }
50
51    pub fn fill_dist_f64<T: Distribution<f64>>(
52        &self,
53        source: &mut Source,
54        dist: T,
55        bound: f64,
56        a: &mut PolyRNS<u64>,
57    ) {
58        (0..a.n()).for_each(|j| {
59            let mut dist_f64: f64 = dist.sample(source);
60
61            while dist_f64.abs() > bound {
62                dist_f64 = dist.sample(source)
63            }
64
65            let dist_u64: u64 = (dist_f64 + 0.5).abs().to_u64().unwrap();
66            let sign: u64 = dist_f64.to_bits() >> 63;
67
68            self.0.iter().enumerate().for_each(|(i, r)| {
69                a.at_mut(i).0[j] = (dist_u64 * sign) | (r.modulus.q - dist_u64) * (sign ^ 1);
70            })
71        })
72    }
73}