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::GALOISGENERATOR;
 3
 4#[derive(Copy, Clone)]
 5#[repr(u8)]
 6pub enum BACKEND {
 7    FFT64,
 8    NTT120,
 9}
10
11pub struct Module {
12    pub ptr: *mut MODULE,
13    pub n: usize,
14    pub backend: BACKEND,
15}
16
17impl Module {
18    // Instantiates a new module.
19    pub fn new(n: usize, module_type: BACKEND) -> Self {
20        unsafe {
21            let module_type_u32: u32;
22            match module_type {
23                BACKEND::FFT64 => module_type_u32 = 0,
24                BACKEND::NTT120 => module_type_u32 = 1,
25            }
26            let m: *mut module_info_t = new_module_info(n as u64, module_type_u32);
27            if m.is_null() {
28                panic!("Failed to create module.");
29            }
30            Self {
31                ptr: m,
32                n: n,
33                backend: module_type,
34            }
35        }
36    }
37
38    pub fn backend(&self) -> BACKEND {
39        self.backend
40    }
41
42    pub fn n(&self) -> usize {
43        self.n
44    }
45
46    pub fn log_n(&self) -> usize {
47        (usize::BITS - (self.n() - 1).leading_zeros()) as _
48    }
49
50    pub fn cyclotomic_order(&self) -> u64 {
51        (self.n() << 1) as _
52    }
53
54    // Returns GALOISGENERATOR^|gen| * sign(gen)
55    pub fn galois_element(&self, gen: i64) -> i64 {
56        if gen == 0 {
57            return 1;
58        }
59        ((mod_exp_u64(GALOISGENERATOR, gen.abs() as usize) & (self.cyclotomic_order() - 1)) as i64)
60            * gen.signum()
61    }
62
63    // Returns gen^-1
64    pub fn galois_element_inv(&self, gen: i64) -> i64 {
65        if gen == 0 {
66            panic!("cannot invert 0")
67        }
68        ((mod_exp_u64(gen.abs() as u64, (self.cyclotomic_order() - 1) as usize)
69            & (self.cyclotomic_order() - 1)) as i64)
70            * gen.signum()
71    }
72
73    pub fn free(self) {
74        unsafe { delete_module_info(self.ptr) }
75        drop(self);
76    }
77}
78
79fn mod_exp_u64(x: u64, e: usize) -> u64 {
80    let mut y: u64 = 1;
81    let mut x_pow: u64 = x;
82    let mut exp = e;
83    while exp > 0 {
84        if exp & 1 == 1 {
85            y = y.wrapping_mul(x_pow);
86        }
87        x_pow = x_pow.wrapping_mul(x_pow);
88        exp >>= 1;
89    }
90    y
91}