use crate::ffi::module::{delete_module_info, module_info_t, new_module_info, MODULE}; use crate::{Free, GALOISGENERATOR}; pub type MODULETYPE = u8; pub const FFT64: u8 = 0; pub const NTT120: u8 = 1; pub struct Module(pub *mut MODULE, pub usize); impl Module { // Instantiates a new module. pub fn new(n: usize) -> Self { unsafe { let m: *mut module_info_t = new_module_info(n as u64, MODULETYPE as u32); if m.is_null() { panic!("Failed to create module."); } Self(m, n) } } pub fn n(&self) -> usize { self.1 } pub fn log_n(&self) -> usize { (usize::BITS - (self.n() - 1).leading_zeros()) as _ } pub fn cyclotomic_order(&self) -> u64 { (self.n() << 1) as _ } // GALOISGENERATOR^|gen| * sign(gen) pub fn galois_element(&self, gen: i64) -> i64 { if gen == 0 { return 1; } let mut gal_el: u64 = 1; let mut gen_1_pow: u64 = GALOISGENERATOR; let mut e: usize = gen.abs() as usize; while e > 0 { if e & 1 == 1 { gal_el = gal_el.wrapping_mul(gen_1_pow); } gen_1_pow = gen_1_pow.wrapping_mul(gen_1_pow); e >>= 1; } gal_el &= self.cyclotomic_order() - 1; (gal_el as i64) * gen.signum() } } impl Free for Module { fn free(self) { unsafe { delete_module_info(self.0) } drop(self); } } pub trait Bytes { /// Returns the minimum number of bytes necessary to allocate /// a new [VecZnxBig] through [VecZnxBig::from_bytes]. fn bytes_of_vec_znx_big(&self, limbs: usize) -> usize; /// Returns the minimum number of bytes necessary to allocate /// a new [VecZnxDft] through [VecZnxDft::from_bytes]. fn vec_znx_idft_tmp_bytes(&self) -> usize; /// Returns a new [VecZnxDft] with the provided bytes array as backing array. /// /// # Arguments /// /// * `limbs`: the number of limbs of the [VecZnxDft]. /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft]. /// /// # Panics /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft]. fn bytes_of_vec_znx_dft(&self, limbs: usize) -> usize; fn vec_znx_big_normalize_tmp_bytes(&self) -> usize; }