poulpy/math/src/ring/impl_u64/ring.rs
math/src/ring/impl_u64/ring.rsRaw
1use crate::dft::ntt::Table;
2use crate::modulus::barrett::Barrett;
3use crate::modulus::montgomery::Montgomery;
4use crate::modulus::prime::Prime;
5use crate::modulus::VectorOperations;
6use crate::modulus::{BARRETT, REDUCEMOD};
7use crate::poly::Poly;
8use crate::ring::Ring;
9use crate::CHUNK;
10use num_bigint::BigInt;
11use num_traits::ToPrimitive;
12
13impl Ring<u64> {
14 pub fn new(n: usize, q_base: u64, q_power: usize) -> Self {
15 let prime: Prime<u64> = Prime::<u64>::new(q_base, q_power);
16 Self {
17 n: n,
18 modulus: prime.clone(),
19 cyclotomic_order: n << 1,
20 dft: Box::new(Table::<u64>::new(prime, n << 1)),
21 }
22 }
23
24 pub fn from_bigint(&self, coeffs: &[BigInt], step: usize, a: &mut Poly<u64>) {
25 assert!(
26 step <= a.n(),
27 "invalid step: step={} > a.n()={}",
28 step,
29 a.n()
30 );
31 assert!(
32 coeffs.len() <= a.n() / step,
33 "invalid coeffs: coeffs.len()={} > a.n()/step={}",
34 coeffs.len(),
35 a.n() / step
36 );
37 let q_big: BigInt = BigInt::from(self.modulus.q);
38 a.0.iter_mut()
39 .step_by(step)
40 .enumerate()
41 .for_each(|(i, v)| *v = (&coeffs[i] % &q_big).to_u64().unwrap());
42 }
43}
44
45impl Ring<u64> {
46 pub fn ntt_inplace<const LAZY: bool>(&self, poly: &mut Poly<u64>) {
47 match LAZY {
48 true => self.dft.forward_inplace_lazy(&mut poly.0),
49 false => self.dft.forward_inplace(&mut poly.0),
50 }
51 }
52
53 pub fn intt_inplace<const LAZY: bool>(&self, poly: &mut Poly<u64>) {
54 match LAZY {
55 true => self.dft.backward_inplace_lazy(&mut poly.0),
56 false => self.dft.backward_inplace(&mut poly.0),
57 }
58 }
59
60 pub fn ntt<const LAZY: bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>) {
61 poly_out.0.copy_from_slice(&poly_in.0);
62 match LAZY {
63 true => self.dft.forward_inplace_lazy(&mut poly_out.0),
64 false => self.dft.forward_inplace(&mut poly_out.0),
65 }
66 }
67
68 pub fn intt<const LAZY: bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>) {
69 poly_out.0.copy_from_slice(&poly_in.0);
70 match LAZY {
71 true => self.dft.backward_inplace_lazy(&mut poly_out.0),
72 false => self.dft.backward_inplace(&mut poly_out.0),
73 }
74 }
75}
76
77impl Ring<u64> {
78 #[inline(always)]
79 pub fn a_add_b_into_b<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>) {
80 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
81 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
82 self.modulus
83 .va_add_vb_into_vb::<CHUNK, REDUCE>(&a.0, &mut b.0);
84 }
85
86 #[inline(always)]
87 pub fn a_add_b_into_c<const REDUCE: REDUCEMOD>(
88 &self,
89 a: &Poly<u64>,
90 b: &Poly<u64>,
91 c: &mut Poly<u64>,
92 ) {
93 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
94 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
95 debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
96 self.modulus
97 .va_add_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
98 }
99
100 #[inline(always)]
101 pub fn a_add_b_scalar_into_a<const REDUCE: REDUCEMOD>(&self, b: &u64, a: &mut Poly<u64>) {
102 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
103 self.modulus.va_add_sb_into_va::<CHUNK, REDUCE>(b, &mut a.0);
104 }
105
106 #[inline(always)]
107 pub fn a_add_b_scalar_into_c<const REDUCE: REDUCEMOD>(
108 &self,
109 a: &Poly<u64>,
110 b: &u64,
111 c: &mut Poly<u64>,
112 ) {
113 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
114 debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
115 self.modulus
116 .va_add_sb_into_vc::<CHUNK, REDUCE>(&a.0, b, &mut c.0);
117 }
118
119 #[inline(always)]
120 pub fn a_add_scalar_b_mul_c_scalar_barrett_into_a<const REDUCE: REDUCEMOD>(
121 &self,
122 b: &u64,
123 c: &Barrett<u64>,
124 a: &mut Poly<u64>,
125 ) {
126 debug_assert!(a.n() == self.n(), "b.n()={} != n={}", a.n(), self.n());
127 self.modulus
128 .va_add_sb_mul_sc_into_va::<CHUNK, REDUCE>(b, c, &mut a.0);
129 }
130
131 #[inline(always)]
132 pub fn add_scalar_then_mul_scalar_barrett<const REDUCE: REDUCEMOD>(
133 &self,
134 a: &Poly<u64>,
135 b: &u64,
136 c: &Barrett<u64>,
137 d: &mut Poly<u64>,
138 ) {
139 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
140 debug_assert!(d.n() == self.n(), "c.n()={} != n={}", d.n(), self.n());
141 self.modulus
142 .va_add_sb_mul_sc_into_vd::<CHUNK, REDUCE>(&a.0, b, c, &mut d.0);
143 }
144
145 #[inline(always)]
146 pub fn a_sub_b_into_b<const BRANGE: u8, const REDUCE: REDUCEMOD>(
147 &self,
148 a: &Poly<u64>,
149 b: &mut Poly<u64>,
150 ) {
151 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
152 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
153 self.modulus
154 .va_sub_vb_into_vb::<CHUNK, BRANGE, REDUCE>(&a.0, &mut b.0);
155 }
156
157 #[inline(always)]
158 pub fn a_sub_b_into_a<const BRANGE: u8, const REDUCE: REDUCEMOD>(
159 &self,
160 b: &Poly<u64>,
161 a: &mut Poly<u64>,
162 ) {
163 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
164 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
165 self.modulus
166 .va_sub_vb_into_va::<CHUNK, BRANGE, REDUCE>(&b.0, &mut a.0);
167 }
168
169 #[inline(always)]
170 pub fn a_sub_b_into_c<const BRANGE: u8, const REDUCE: REDUCEMOD>(
171 &self,
172 a: &Poly<u64>,
173 b: &Poly<u64>,
174 c: &mut Poly<u64>,
175 ) {
176 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
177 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
178 debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
179 self.modulus
180 .va_sub_vb_into_vc::<CHUNK, BRANGE, REDUCE>(&a.0, &b.0, &mut c.0);
181 }
182
183 #[inline(always)]
184 pub fn a_neg_into_b<const ARANGE: u8, const REDUCE: REDUCEMOD>(
185 &self,
186 a: &Poly<u64>,
187 b: &mut Poly<u64>,
188 ) {
189 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
190 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
191 self.modulus
192 .va_neg_into_vb::<CHUNK, ARANGE, REDUCE>(&a.0, &mut b.0);
193 }
194
195 #[inline(always)]
196 pub fn a_neg_into_a<const ARANGE: u8, const REDUCE: REDUCEMOD>(&self, a: &mut Poly<u64>) {
197 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
198 self.modulus
199 .va_neg_into_va::<CHUNK, ARANGE, REDUCE>(&mut a.0);
200 }
201
202 #[inline(always)]
203 pub fn a_prepare_montgomery_into_a<const REDUCE: REDUCEMOD>(
204 &self,
205 a: &mut Poly<Montgomery<u64>>,
206 ) {
207 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
208 self.modulus
209 .va_prepare_montgomery_into_va::<CHUNK, REDUCE>(&mut a.0);
210 }
211
212 #[inline(always)]
213 pub fn a_mul_b_montgomery_into_c<const REDUCE: REDUCEMOD>(
214 &self,
215 a: &Poly<Montgomery<u64>>,
216 b: &Poly<u64>,
217 c: &mut Poly<u64>,
218 ) {
219 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
220 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
221 debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
222 self.modulus
223 .va_mont_mul_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
224 }
225
226 #[inline(always)]
227 pub fn a_mul_b_montgomery_into_a<const REDUCE: REDUCEMOD>(
228 &self,
229 b: &Poly<Montgomery<u64>>,
230 a: &mut Poly<u64>,
231 ) {
232 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
233 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
234 self.modulus
235 .va_mont_mul_vb_into_vb::<CHUNK, REDUCE>(&b.0, &mut a.0);
236 }
237
238 #[inline(always)]
239 pub fn a_mul_b_scalar_into_c<const REDUCE: REDUCEMOD>(
240 &self,
241 a: &Poly<u64>,
242 b: &u64,
243 c: &mut Poly<u64>,
244 ) {
245 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
246 debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
247 self.modulus.sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(
248 &self.modulus.barrett.prepare(*b),
249 &a.0,
250 &mut c.0,
251 );
252 }
253
254 #[inline(always)]
255 pub fn a_mul_b_scalar_into_a<const REDUCE: REDUCEMOD>(&self, b: &u64, a: &mut Poly<u64>) {
256 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
257 self.modulus.sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(
258 &self
259 .modulus
260 .barrett
261 .prepare(self.modulus.barrett.reduce::<BARRETT>(b)),
262 &mut a.0,
263 );
264 }
265
266 #[inline(always)]
267 pub fn a_mul_b_scalar_barrett_into_a<const REDUCE: REDUCEMOD>(
268 &self,
269 b: &Barrett<u64>,
270 a: &mut Poly<u64>,
271 ) {
272 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
273 self.modulus
274 .sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(b, &mut a.0);
275 }
276
277 #[inline(always)]
278 pub fn a_mul_b_scalar_barrett_into_c<const REDUCE: REDUCEMOD>(
279 &self,
280 a: &Barrett<u64>,
281 b: &Poly<u64>,
282 c: &mut Poly<u64>,
283 ) {
284 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
285 self.modulus
286 .sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(a, &b.0, &mut c.0);
287 }
288
289 #[inline(always)]
290 pub fn a_sub_b_mul_c_scalar_barrett_into_d<const VBRANGE: u8, const REDUCE: REDUCEMOD>(
291 &self,
292 a: &Poly<u64>,
293 b: &Poly<u64>,
294 c: &Barrett<u64>,
295 d: &mut Poly<u64>,
296 ) {
297 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
298 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
299 debug_assert!(d.n() == self.n(), "d.n()={} != n={}", d.n(), self.n());
300 self.modulus
301 .va_sub_vb_mul_sc_into_vd::<CHUNK, VBRANGE, REDUCE>(&a.0, &b.0, c, &mut d.0);
302 }
303
304 #[inline(always)]
305 pub fn b_sub_a_mul_c_scalar_barrett_into_a<const BRANGE: u8, const REDUCE: REDUCEMOD>(
306 &self,
307 b: &Poly<u64>,
308 c: &Barrett<u64>,
309 a: &mut Poly<u64>,
310 ) {
311 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
312 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
313 self.modulus
314 .va_sub_vb_mul_sc_into_vb::<CHUNK, BRANGE, REDUCE>(&b.0, c, &mut a.0);
315 }
316
317 #[inline(always)]
318 pub fn a_sub_b_add_c_scalar_mul_d_scalar_barrett_into_e<
319 const BRANGE: u8,
320 const REDUCE: REDUCEMOD,
321 >(
322 &self,
323 a: &Poly<u64>,
324 b: &Poly<u64>,
325 c: &u64,
326 d: &Barrett<u64>,
327 e: &mut Poly<u64>,
328 ) {
329 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
330 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
331 debug_assert!(e.n() == self.n(), "e.n()={} != n={}", e.n(), self.n());
332 self.modulus
333 .vb_sub_va_add_sc_mul_sd_into_ve::<CHUNK, BRANGE, REDUCE>(&a.0, &b.0, c, d, &mut e.0);
334 }
335
336 #[inline(always)]
337 pub fn b_sub_a_add_c_scalar_mul_d_scalar_barrett_into_a<
338 const BRANGE: u8,
339 const REDUCE: REDUCEMOD,
340 >(
341 &self,
342 b: &Poly<u64>,
343 c: &u64,
344 d: &Barrett<u64>,
345 a: &mut Poly<u64>,
346 ) {
347 debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
348 debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
349 self.modulus
350 .vb_sub_va_add_sc_mul_sd_into_va::<CHUNK, BRANGE, REDUCE>(&b.0, c, d, &mut a.0);
351 }
352}