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;
 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}