arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/math/src/ring.rs
math/src/ring.rsRaw
 1pub mod impl_u64;
 2use crate::dft::DFT;
 3use crate::modulus::prime::Prime;
 4use crate::modulus::WordOps;
 5use crate::poly::{Poly, PolyRNS};
 6use crate::GALOISGENERATOR;
 7use num::traits::Unsigned;
 8use std::rc::Rc;
 9
10pub struct Ring<O: Unsigned> {
11    pub n: usize,
12    pub modulus: Prime<O>,
13    pub cyclotomic_order: usize,
14    pub dft: Box<dyn DFT<O>>,
15}
16
17impl<O: Unsigned> Ring<O> {
18    pub fn log_n(&self) -> usize {
19        return self.n().log2();
20    }
21
22    pub fn n(&self) -> usize {
23        return self.n;
24    }
25
26    pub fn new_poly(&self) -> Poly<u64> {
27        Poly::<u64>::new(self.n())
28    }
29
30    pub fn cyclotomic_order(&self) -> usize {
31        self.cyclotomic_order
32    }
33
34    // Returns GALOISGENERATOR^gen_1 * (-1)^gen_2 mod 2^log_nth_root.
35    pub fn galois_element(&self, gen_1: usize, gen_2: bool) -> usize {
36        let mut gal_el: usize = 1;
37        let mut gen_1_pow: usize = GALOISGENERATOR;
38        let mut e: usize = gen_1;
39        while e > 0 {
40            if e & 1 == 1 {
41                gal_el = gal_el.wrapping_mul(gen_1_pow);
42            }
43
44            gen_1_pow = gen_1_pow.wrapping_mul(gen_1_pow);
45            e >>= 1;
46        }
47
48        gal_el &= self.cyclotomic_order - 1;
49
50        if gen_2 {
51            return self.cyclotomic_order - gal_el;
52        }
53        gal_el
54    }
55}
56
57pub struct RingRNS<O: Unsigned>(pub Vec<Rc<Ring<O>>>);
58
59impl<O: Unsigned> RingRNS<O> {
60    pub fn log_n(&self) -> usize {
61        return self.n().log2();
62    }
63
64    pub fn n(&self) -> usize {
65        self.0[0].n()
66    }
67
68    pub fn new_polyrns(&self) -> PolyRNS<u64> {
69        PolyRNS::<u64>::new(self.n(), self.level())
70    }
71
72    pub fn new_poly(&self) -> Poly<u64> {
73        Poly::<u64>::new(self.n())
74    }
75
76    pub fn max_level(&self) -> usize {
77        self.0.len() - 1
78    }
79
80    pub fn level(&self) -> usize {
81        self.0.len() - 1
82    }
83
84    pub fn at_level(&self, level: usize) -> RingRNS<O> {
85        assert!(level <= self.0.len());
86        RingRNS(self.0[..level + 1].to_vec())
87    }
88}