1use crate::{Polynomial, RingParams};
3use rand::{Rng, RngCore, rngs::OsRng};
4use std::ops::Deref;
5
6#[derive(Clone, Debug)]
7pub struct Sample(pub Vec<i32>);
8
9impl Deref for Sample {
10 type Target = Vec<i32>;
11
12 fn deref(&self) -> &Self::Target {
13 &self.0
14 }
15}
16
17impl Sample {
18 pub fn to_poly(self, q:u64) -> Polynomial {
19 let coeffs = self.iter().map(|v| (*v).rem_euclid(q as i32) as u64).collect();
20 Polynomial::new(coeffs)
21 }
22}
23
24
25
26#[inline]
27pub fn generate_cbd_sample(n: usize, eta: usize) -> Sample { let mut coeffs = vec![0i32; n]; let bits_per_coeff = eta; let total_bits = 2 * coeffs.len() * bits_per_coeff;
41
42 let total_bytes = (total_bits + 7) / 8;
43
44 let mut rng_buf = vec![0u8; total_bytes];
45
46 OsRng.fill_bytes(&mut rng_buf); let mut bit_index = 0;
48 for coeff in coeffs.iter_mut() {
49 let mut a = 0;
50 let mut b = 0;
51
52 for _ in 0..bits_per_coeff { let byte = rng_buf[bit_index / 8];
54 let bit = (byte >> (bit_index % 8)) & 1;
55 a += bit as u64;
56 bit_index += 1;
57 }
58
59 for _ in 0..bits_per_coeff { let byte = rng_buf[bit_index / 8];
61 let bit = (byte >> (bit_index % 8)) & 1;
62 b += bit as u64;
63 bit_index += 1;
64 }
65
66 *coeff = a as i32 - b as i32; }
68
69 Sample(coeffs)
70}
71
72
73#[inline]
74pub fn generate_small_sample(params: &RingParams) -> Sample { let mut rng = OsRng;
76 let mut coeffs: Vec<i32> = Vec::with_capacity(params.n);
77
78 for _ in 0..params.n {
79 let small: i32 = rng.gen_range(-1..=1); coeffs.push(small);
81 }
82
83 Sample(coeffs)
84}
85
86#[inline]
87pub fn generate_uniform_polynomial(params: &RingParams) -> Polynomial { let mut rng = OsRng;
89 let mut coeffs = Vec::with_capacity(params.n);
90
91 for _ in 0..params.n {
92 let uniform: u64 = rng.gen_range(0..=params.q - 1); coeffs.push(uniform);
94 }
95
96 Polynomial { coeffs: coeffs.into_boxed_slice() }
97}