arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/module.rs
base2k/src/module.rsRaw
 1use crate::ffi::module::{delete_module_info, module_info_t, new_module_info, MODULE};
 2use crate::{Free, GALOISGENERATOR};
 3
 4pub type MODULETYPE = u8;
 5pub const FFT64: u8 = 0;
 6pub const NTT120: u8 = 1;
 7
 8pub struct Module(pub *mut MODULE, pub usize);
 9
10impl Module {
11    // Instantiates a new module.
12    pub fn new<const MODULETYPE: MODULETYPE>(n: usize) -> Self {
13        unsafe {
14            let m: *mut module_info_t = new_module_info(n as u64, MODULETYPE as u32);
15            if m.is_null() {
16                panic!("Failed to create module.");
17            }
18            Self(m, n)
19        }
20    }
21
22    pub fn n(&self) -> usize {
23        self.1
24    }
25
26    pub fn log_n(&self) -> usize {
27        (usize::BITS - (self.n() - 1).leading_zeros()) as _
28    }
29
30    pub fn cyclotomic_order(&self) -> u64 {
31        (self.n() << 1) as _
32    }
33
34    // GALOISGENERATOR^|gen| * sign(gen)
35    pub fn galois_element(&self, gen: i64) -> i64 {
36        if gen == 0 {
37            return 1;
38        }
39
40        let mut gal_el: u64 = 1;
41        let mut gen_1_pow: u64 = GALOISGENERATOR;
42        let mut e: usize = gen.abs() as usize;
43        while e > 0 {
44            if e & 1 == 1 {
45                gal_el = gal_el.wrapping_mul(gen_1_pow);
46            }
47
48            gen_1_pow = gen_1_pow.wrapping_mul(gen_1_pow);
49            e >>= 1;
50        }
51
52        gal_el &= self.cyclotomic_order() - 1;
53
54        (gal_el as i64) * gen.signum()
55    }
56}
57
58impl Free for Module {
59    fn free(self) {
60        unsafe { delete_module_info(self.0) }
61        drop(self);
62    }
63}