poulpy/math/src/ring/impl_u64/ring_rns.rs
math/src/ring/impl_u64/ring_rns.rsRaw
1use crate::ring::{Ring, RingRNS};
2use crate::poly::PolyRNS;
3use crate::modulus::montgomery::Montgomery;
4use crate::modulus::barrett::Barrett;
5use crate::modulus::REDUCEMOD;
6use num_bigint::BigInt;
7
8pub fn new_rings(n: usize, moduli: Vec<u64>) -> Vec<Ring<u64>>{
9 assert!(!moduli.is_empty(), "moduli cannot be empty");
10 let rings: Vec<Ring<u64>> = moduli
11 .into_iter()
12 .map(|prime| Ring::new(n, prime, 1))
13 .collect();
14 return rings
15}
16
17impl<'a> RingRNS<'a, u64>{
18 pub fn new(rings:&'a [Ring<u64>]) -> Self{
19 RingRNS(rings)
20 }
21
22 pub fn rescaling_constant(&self) -> Vec<Barrett<u64>> {
23 let level = self.level();
24 let q_scale: u64 = self.0[level].modulus.q;
25 (0..level).map(|i| {self.0[i].modulus.barrett.prepare(self.0[i].modulus.q - self.0[i].modulus.inv(q_scale))}).collect()
26 }
27
28 pub fn set_poly_from_bigint(&self, coeffs: &[BigInt], step:usize, a: &mut PolyRNS<u64>){
29 let level = self.level();
30 assert!(level <= a.level(), "invalid level: level={} > a.level()={}", level, a.level());
31 (0..level).for_each(|i|{self.0[i].from_bigint(coeffs, step, a.at_mut(i))});
32 }
33}
34
35impl RingRNS<'_, u64>{
36
37 #[inline(always)]
38 pub fn add<const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &PolyRNS<u64>, c: &mut PolyRNS<u64>){
39 let level: usize = self.level();
40 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
41 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
42 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
43 debug_assert!(c.level() >= level, "c.level()={} < level={}", c.level(), level);
44 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.add::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
45 }
46
47 #[inline(always)]
48 pub fn add_inplace<const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
49 let level: usize = self.level();
50 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
51 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
52 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
53 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.add_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
54 }
55
56 #[inline(always)]
57 pub fn sub<const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &PolyRNS<u64>, c: &mut PolyRNS<u64>){
58 let level: usize = self.level();
59 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
60 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
61 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
62 debug_assert!(c.level() >= level, "c.level()={} < level={}", c.level(), level);
63 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.sub::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
64 }
65
66 #[inline(always)]
67 pub fn sub_inplace<const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
68 let level: usize = self.level();
69 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
70 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
71 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
72 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.sub_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
73 }
74
75 #[inline(always)]
76 pub fn neg<const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
77 let level: usize = self.level();
78 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
79 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
80 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
81 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.neg::<REDUCE>(&a.0[i], &mut b.0[i]));
82 }
83
84 #[inline(always)]
85 pub fn neg_inplace<const REDUCE: REDUCEMOD>(&self, a: &mut PolyRNS<u64>){
86 let level: usize = self.level();
87 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
88 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
89 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.neg_inplace::<REDUCE>(&mut a.0[i]));
90 }
91
92 #[inline(always)]
93 pub fn mul_montgomery_external<const REDUCE:REDUCEMOD>(&self, a:&PolyRNS<Montgomery<u64>>, b:&PolyRNS<u64>, c: &mut PolyRNS<u64>){
94 let level: usize = self.level();
95 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
96 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
97 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
98 debug_assert!(c.level() >= level, "c.level()={} < level={}", c.level(), level);
99 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.mul_montgomery_external::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
100 }
101
102 #[inline(always)]
103 pub fn mul_montgomery_external_inplace<const REDUCE:REDUCEMOD>(&self, a:&PolyRNS<Montgomery<u64>>, b:&mut PolyRNS<u64>){
104 let level: usize = self.level();
105 debug_assert!(self.max_level() <= level, "max_level={} < level={}", self.max_level(), level);
106 debug_assert!(a.level() >= level, "a.level()={} < level={}", a.level(), level);
107 debug_assert!(b.level() >= level, "b.level()={} < level={}", b.level(), level);
108 self.0.iter().take(level + 1).enumerate().for_each(|(i, ring)| ring.mul_montgomery_external_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
109 }
110}