use crate::{Polynomial, RingParams};
use rand::{Rng, RngCore, rngs::OsRng};
use std::ops::Deref;
#[derive(Clone, Debug)]
pub struct Sample(pub Vec<i32>);
impl Deref for Sample {
type Target = Vec<i32>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Sample {
pub fn to_poly(self, q:u64) -> Polynomial {
let coeffs = self.iter().map(|v| (*v).rem_euclid(q as i32) as u64).collect();
Polynomial::new(coeffs)
}
}
#[inline]
pub 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;
let total_bytes = (total_bits + 7) / 8;
let mut rng_buf = vec![0u8; total_bytes];
OsRng.fill_bytes(&mut rng_buf); let mut bit_index = 0;
for coeff in coeffs.iter_mut() {
let mut a = 0;
let mut b = 0;
for _ in 0..bits_per_coeff { let byte = rng_buf[bit_index / 8];
let bit = (byte >> (bit_index % 8)) & 1;
a += bit as u64;
bit_index += 1;
}
for _ in 0..bits_per_coeff { let byte = rng_buf[bit_index / 8];
let bit = (byte >> (bit_index % 8)) & 1;
b += bit as u64;
bit_index += 1;
}
*coeff = a as i32 - b as i32; }
Sample(coeffs)
}
#[inline]
pub fn generate_small_sample(params: &RingParams) -> Sample { let mut rng = OsRng;
let mut coeffs: Vec<i32> = Vec::with_capacity(params.n);
for _ in 0..params.n {
let small: i32 = rng.gen_range(-1..=1); coeffs.push(small);
}
Sample(coeffs)
}
#[inline]
pub fn generate_uniform_polynomial(params: &RingParams) -> Polynomial { let mut rng = OsRng;
let mut coeffs = Vec::with_capacity(params.n);
for _ in 0..params.n {
let uniform: u64 = rng.gen_range(0..=params.q - 1); coeffs.push(uniform);
}
Polynomial { coeffs: coeffs.into_boxed_slice() }
}