use crate::{
error::MathError,
integer::PolyOverZ,
rational::Q,
traits::SetCoefficient,
utils::{
index::evaluate_index,
sample::discrete_gauss::{DiscreteGaussianIntegerSampler, LookupTableSetting, TAILCUT},
},
};
use std::fmt::Display;
impl PolyOverZ {
pub fn sample_discrete_gauss(
max_degree: impl TryInto<i64> + Display,
center: impl Into<Q>,
s: impl Into<Q>,
) -> Result<Self, MathError> {
let max_degree = evaluate_index(max_degree).unwrap();
let center = center.into();
let s = s.into();
let mut poly = PolyOverZ::default();
let mut dgis = DiscreteGaussianIntegerSampler::init(
¢er,
&s,
unsafe { TAILCUT },
LookupTableSetting::FillOnTheFly,
)?;
for index in 0..=max_degree {
let sample = dgis.sample_z();
unsafe { poly.set_coeff_unchecked(index, &sample) };
}
Ok(poly)
}
}
#[cfg(test)]
mod test_sample_discrete_gauss {
use crate::{integer::PolyOverZ, rational::Q};
#[test]
fn availability() {
let center = Q::ZERO;
let s = Q::ONE;
let _ = PolyOverZ::sample_discrete_gauss(1u8, 0f32, 1u8);
let _ = PolyOverZ::sample_discrete_gauss(1u16, 0f64, 1u16);
let _ = PolyOverZ::sample_discrete_gauss(1u32, 0f32, 1u32);
let _ = PolyOverZ::sample_discrete_gauss(1u64, 0f64, 1u64);
let _ = PolyOverZ::sample_discrete_gauss(1i8, 0f32, 1i8);
let _ = PolyOverZ::sample_discrete_gauss(1i8, 0f32, 1i16);
let _ = PolyOverZ::sample_discrete_gauss(1i16, 0f32, 1i32);
let _ = PolyOverZ::sample_discrete_gauss(1i32, 0f64, 1i64);
let _ = PolyOverZ::sample_discrete_gauss(1i64, center, s);
let _ = PolyOverZ::sample_discrete_gauss(1u8, 0f32, 1f64);
}
#[test]
fn nr_coeffs() {
let degrees = [1, 3, 7, 15, 32, 120];
for degree in degrees {
let res = PolyOverZ::sample_discrete_gauss(degree, i64::MAX, 1).unwrap();
assert_eq!(
res.get_degree(),
degree,
"Could fail with negligible probability."
);
}
}
#[test]
#[should_panic]
fn invalid_max_degree() {
let _ = PolyOverZ::sample_discrete_gauss(-1, 0, 1).unwrap();
}
}