use crate::{mat_vec_mul, Matrix, Vector};
pub mod gauss;
use gauss::gauss_sample;
pub fn gen_secret_key(secret_dimension: usize, seed: Option<u64>) -> Vector {
Vector::new_random(secret_dimension, 0..=u64::MAX, seed)
}
pub fn gen_a_matrix(num_samples: usize, secret_dimension: usize, seed: Option<u64>) -> Matrix {
Matrix::new_random(num_samples, secret_dimension, 0..=u64::MAX, seed)
}
pub fn encrypt(
secret_key: &Vector,
a_matrix: &Matrix,
bits: &Vector,
plaintext_mod: u64,
) -> (Matrix, Vector) {
let ciphertext_mod = 2_u128.pow(64);
let q_over_p = (ciphertext_mod / plaintext_mod as u128) as u64;
assert_eq!(
secret_key.len(),
a_matrix.ncols(),
"The number of columns in the a-matrix must match the length of the secret key!"
);
assert_eq!(
bits.len(),
a_matrix.nrows(),
"The number of rows in the a-matrix must match the number of samples!"
);
let num_samples = bits.len();
let error_vector = Vector::from_vec((0..num_samples).map(|_| gauss_sample() as u64).collect());
(
a_matrix.clone(),
mat_vec_mul(secret_key, a_matrix)
.add(&error_vector)
.add(&bits.mul_scalar(q_over_p)),
)
}