poulpy/rns/src/modulus.rs
rns/src/modulus.rsRaw
1pub mod barrett;
2pub mod impl_u64;
3pub mod montgomery;
4pub mod prime;
5
6pub type REDUCEMOD = u8;
7
8pub const NONE: REDUCEMOD = 0;
9pub const ONCE: REDUCEMOD = 1;
10pub const TWICE: REDUCEMOD = 2;
11pub const FOURTIMES: REDUCEMOD = 3;
12pub const BARRETT: REDUCEMOD = 4;
13pub const BARRETTLAZY: REDUCEMOD = 5;
14
15pub trait WordOps<O> {
16 fn log2(self) -> usize;
17 fn reverse_bits_msb(self, n: u32) -> O;
18 fn mask(self) -> O;
19}
20
21impl WordOps<u64> for u64 {
22 #[inline(always)]
23 fn log2(self) -> usize {
24 (u64::BITS - (self - 1).leading_zeros()) as _
25 }
26 #[inline(always)]
27 fn reverse_bits_msb(self, n: u32) -> u64 {
28 self.reverse_bits() >> (usize::BITS - n)
29 }
30 #[inline(always)]
31 fn mask(self) -> u64 {
32 (1 << self.log2()) - 1
33 }
34}
35
36impl WordOps<usize> for usize {
37 #[inline(always)]
38 fn log2(self) -> usize {
39 (usize::BITS - (self - 1).leading_zeros()) as _
40 }
41 #[inline(always)]
42 fn reverse_bits_msb(self, n: u32) -> usize {
43 self.reverse_bits() >> (usize::BITS - n)
44 }
45 #[inline(always)]
46 fn mask(self) -> usize {
47 (1 << self.log2()) - 1
48 }
49}
50
51pub trait ReduceOnce<O> {
52 /// Assigns self-q to self if self >= q in constant time.
53 /// User must ensure that 2q fits in O.
54 fn reduce_once_constant_time_assign(&mut self, q: O);
55 /// Returns self-q if self >= q else self in constant time.
56 /// /// User must ensure that 2q fits in O.
57 fn reduce_once_constant_time(&self, q: O) -> O;
58 /// Assigns self-q to self if self >= q.
59 /// /// User must ensure that 2q fits in O.
60 fn reduce_once_assign(&mut self, q: O);
61 /// Returns self-q if self >= q else self.
62 /// /// User must ensure that 2q fits in O.
63 fn reduce_once(&self, q: O) -> O;
64}
65
66pub trait ScalarOperations<O> {
67 // Applies a parameterized modular reduction.
68 fn sa_reduce_into_sa<const REDUCE: REDUCEMOD>(&self, x: &mut O);
69
70 // Assigns a + b to c.
71 fn sa_add_sb_into_sc<const REDUCE: REDUCEMOD>(&self, a: &O, b: &O, c: &mut O);
72
73 // Assigns a + b to b.
74 fn sa_add_sb_into_sb<const REDUCE: REDUCEMOD>(&self, a: &O, b: &mut O);
75
76 // Assigns a - b to c.
77 fn sa_sub_sb_into_sc<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
78 &self,
79 a: &O,
80 b: &O,
81 c: &mut O,
82 );
83
84 // Assigns a - b to b.
85 fn sa_sub_sb_into_sb<const SARANGE: u8, const REDUCE: REDUCEMOD>(&self, a: &O, b: &mut O);
86
87 // Assigns a - b to a.
88 fn sa_sub_sb_into_sa<const SARANGE: u8, const REDUCE: REDUCEMOD>(&self, b: &O, a: &mut O);
89
90 // Assigns -a to a.
91 fn sa_neg_into_sa<const SBRANGE: u8, const REDUCE: REDUCEMOD>(&self, a: &mut O);
92
93 // Assigns -a to b.
94 fn sa_neg_into_sb<const SARANGE: u8, const REDUCE: REDUCEMOD>(&self, a: &O, b: &mut O);
95
96 // Assigns a * 2^64 to a.
97 fn sa_prepare_montgomery_into_sa<const REDUCE: REDUCEMOD>(
98 &self,
99 a: &mut montgomery::Montgomery<O>,
100 );
101
102 // Assigns a * 2^64 to b.
103 fn sa_prepare_montgomery_into_sb<const REDUCE: REDUCEMOD>(
104 &self,
105 a: &O,
106 b: &mut montgomery::Montgomery<O>,
107 );
108
109 // Assigns a * b to c.
110 fn sa_mul_sb_montgomery_into_sc<const REDUCE: REDUCEMOD>(
111 &self,
112 a: &O,
113 b: &montgomery::Montgomery<O>,
114 c: &mut O,
115 );
116
117 // Assigns a * b + c to c.
118 fn sa_mul_sb_montgomery_add_sc_into_sc<const REDUCE1: REDUCEMOD, const REDUCE2: REDUCEMOD>(
119 &self,
120 a: &O,
121 b: &montgomery::Montgomery<O>,
122 c: &mut O,
123 );
124
125 // Assigns a * b to b.
126 fn sa_mul_sb_montgomery_into_sa<const REDUCE: REDUCEMOD>(
127 &self,
128 b: &montgomery::Montgomery<O>,
129 a: &mut O,
130 );
131
132 // Assigns a * b to c.
133 fn sa_mul_sb_barrett_into_sc<const REDUCE: REDUCEMOD>(
134 &self,
135 a: &O,
136 b: &barrett::Barrett<O>,
137 c: &mut O,
138 );
139
140 // Assigns a * b to a.
141 fn sa_mul_sb_barrett_into_sa<const REDUCE: REDUCEMOD>(
142 &self,
143 b: &barrett::Barrett<O>,
144 a: &mut O,
145 );
146
147 // Assigns (a + q - b) * c to d.
148 fn sa_sub_sb_mul_sc_barrett_into_sd<const VBRANGE: u8, const REDUCE: REDUCEMOD>(
149 &self,
150 a: &O,
151 b: &O,
152 c: &barrett::Barrett<O>,
153 d: &mut O,
154 );
155
156 // Assigns (a + q - b) * c to b.
157 fn sa_sub_sb_mul_sc_barrett_into_sb<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
158 &self,
159 a: &u64,
160 c: &barrett::Barrett<u64>,
161 b: &mut u64,
162 );
163
164 // Assigns (a + b) * c to a.
165 fn sa_add_sb_mul_sc_barrett_into_sa<const REDUCE: REDUCEMOD>(
166 &self,
167 b: &u64,
168 c: &barrett::Barrett<u64>,
169 a: &mut u64,
170 );
171
172 // Assigns (a + b) * c to d.
173 fn sa_add_sb_mul_sc_barrett_into_sd<const REDUCE: REDUCEMOD>(
174 &self,
175 a: &u64,
176 b: &u64,
177 c: &barrett::Barrett<u64>,
178 d: &mut u64,
179 );
180
181 // Assigns (a - b + c) * d to e.
182 fn sb_sub_sa_add_sc_mul_sd_barrett_into_se<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
183 &self,
184 a: &u64,
185 b: &u64,
186 c: &u64,
187 d: &barrett::Barrett<u64>,
188 e: &mut u64,
189 );
190
191 fn sb_sub_sa_add_sc_mul_sd_barrett_into_sa<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
192 &self,
193 b: &u64,
194 c: &u64,
195 d: &barrett::Barrett<u64>,
196 a: &mut u64,
197 );
198
199 fn sa_rsh_sb_mask_sc_into_sa(&self, c: &usize, b: &u64, a: &mut u64);
200
201 fn sa_rsh_sb_mask_sc_into_sd(&self, a: &u64, b: &usize, c: &u64, d: &mut u64);
202
203 fn sa_rsh_sb_mask_sc_add_sd_into_sd(&self, a: &u64, b: &usize, c: &u64, d: &mut u64);
204
205 fn sa_signed_digit_into_sb<const CARRYOVERWRITE: bool, const BALANCED: bool>(
206 &self,
207 a: &u64,
208 base: &u64,
209 shift: &usize,
210 mask: &u64,
211 carry: &mut u64,
212 b: &mut u64,
213 );
214}
215
216pub trait VectorOperations<O> {
217 // Applies a parameterized modular reduction.
218 fn va_reduce_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, x: &mut [O]);
219
220 // ADD
221 // vec(c) <- vec(a) + vec(b).
222 fn va_add_vb_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
223 &self,
224 va: &[O],
225 vb: &[O],
226 vc: &mut [O],
227 );
228
229 // vec(b) <- vec(a) + vec(b).
230 fn va_add_vb_into_vb<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, a: &[O], b: &mut [O]);
231
232 // vec(c) <- vec(a) + scalar(b).
233 fn va_add_sb_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
234 &self,
235 a: &[O],
236 b: &O,
237 c: &mut [O],
238 );
239
240 // vec(b) <- vec(b) + scalar(a).
241 fn va_add_sb_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, a: &O, b: &mut [O]);
242
243 // vec(b) <- vec(a) - vec(b).
244 fn va_sub_vb_into_vb<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
245 &self,
246 a: &[O],
247 b: &mut [O],
248 );
249
250 // vec(a) <- vec(a) - vec(b).
251 fn va_sub_vb_into_va<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
252 &self,
253 b: &[O],
254 a: &mut [O],
255 );
256
257 // vec(c) <- vec(a) - vec(b).
258 fn va_sub_vb_into_vc<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
259 &self,
260 a: &[O],
261 b: &[O],
262 c: &mut [O],
263 );
264
265 // vec(a) <- -vec(a).
266 fn va_neg_into_va<const CHUNK: usize, const VARANGE: u8, const REDUCE: REDUCEMOD>(
267 &self,
268 a: &mut [O],
269 );
270
271 // vec(b) <- -vec(a).
272 fn va_neg_into_vb<const CHUNK: usize, const VARANGE: u8, const REDUCE: REDUCEMOD>(
273 &self,
274 a: &[O],
275 b: &mut [O],
276 );
277
278 // vec(b) <- vec(a)
279 fn va_prep_mont_into_vb<const CHUNK: usize, const REDUCE: REDUCEMOD>(
280 &self,
281 a: &[O],
282 b: &mut [montgomery::Montgomery<O>],
283 );
284
285 // vec(a) <- vec(a).
286 fn va_prepare_montgomery_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
287 &self,
288 a: &mut [montgomery::Montgomery<O>],
289 );
290
291 // vec(c) <- vec(a) * vec(b).
292 fn va_mul_vb_montgomery_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
293 &self,
294 a: &[O],
295 b: &[montgomery::Montgomery<O>],
296 c: &mut [O],
297 );
298
299 // vec(c) <- vec(a) * vec(b) + vec(c).
300 fn va_mul_vb_montgomery_add_vc_into_vc<
301 const CHUNK: usize,
302 const REDUCE1: REDUCEMOD,
303 const REDUCE2: REDUCEMOD,
304 >(
305 &self,
306 a: &[O],
307 b: &[montgomery::Montgomery<O>],
308 c: &mut [O],
309 );
310
311 // vec(a) <- vec(a) * vec(b).
312 fn va_mul_vb_montgomery_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
313 &self,
314 b: &[montgomery::Montgomery<O>],
315 a: &mut [O],
316 );
317
318 // vec(b) <- vec(a) * scalar(b).
319 fn va_mul_sb_barrett_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
320 &self,
321 b: &barrett::Barrett<u64>,
322 a: &mut [u64],
323 );
324
325 // vec(c) <- vec(a) * scalar(b).
326 fn va_mul_sb_barrett_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
327 &self,
328 a: &[u64],
329 b: &barrett::Barrett<u64>,
330 c: &mut [u64],
331 );
332
333 // vec(d) <- (vec(a) + VBRANGE * q - vec(b)) * scalar(c).
334 fn va_sub_vb_mul_sc_barrett_into_vd<
335 const CHUNK: usize,
336 const VBRANGE: u8,
337 const REDUCE: REDUCEMOD,
338 >(
339 &self,
340 a: &[u64],
341 b: &[u64],
342 c: &barrett::Barrett<u64>,
343 d: &mut [u64],
344 );
345
346 // vec(b) <- (vec(a) + VBRANGE * q - vec(b)) * scalar(c).
347 fn va_sub_vb_mul_sc_barrett_into_vb<
348 const CHUNK: usize,
349 const VBRANGE: u8,
350 const REDUCE: REDUCEMOD,
351 >(
352 &self,
353 a: &[u64],
354 c: &barrett::Barrett<u64>,
355 b: &mut [u64],
356 );
357
358 // vec(c) <- (vec(a) + scalar(b)) * scalar(c).
359 fn va_add_sb_mul_sc_barrett_into_vd<const CHUNK: usize, const REDUCE: REDUCEMOD>(
360 &self,
361 va: &[u64],
362 sb: &u64,
363 sc: &barrett::Barrett<u64>,
364 vd: &mut [u64],
365 );
366
367 // vec(a) <- (vec(a) + scalar(b)) * scalar(c).
368 fn va_add_sb_mul_sc_barrett_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
369 &self,
370 sb: &u64,
371 sc: &barrett::Barrett<u64>,
372 va: &mut [u64],
373 );
374
375 // vec(e) <- (vec(b) - vec(a) + scalar(c)) * scalar(e).
376 fn vb_sub_va_add_sc_mul_sd_barrett_into_ve<
377 const CHUNK: usize,
378 const VBRANGE: u8,
379 const REDUCE: REDUCEMOD,
380 >(
381 &self,
382 va: &[u64],
383 vb: &[u64],
384 sc: &u64,
385 sd: &barrett::Barrett<u64>,
386 ve: &mut [u64],
387 );
388
389 // vec(a) <- (vec(b) - vec(a) + scalar(c)) * scalar(e).
390 fn vb_sub_va_add_sc_mul_sd_barrett_into_va<
391 const CHUNK: usize,
392 const VBRANGE: u8,
393 const REDUCE: REDUCEMOD,
394 >(
395 &self,
396 vb: &[u64],
397 sc: &u64,
398 sd: &barrett::Barrett<u64>,
399 va: &mut [u64],
400 );
401
402 // vec(a) <- (vec(a)>>scalar(b)) & scalar(c).
403 fn va_rsh_sb_mask_sc_into_va<const CHUNK: usize>(&self, sb: &usize, sc: &u64, va: &mut [u64]);
404
405 // vec(d) <- (vec(a)>>scalar(b)) & scalar(c).
406 fn va_rsh_sb_mask_sc_into_vd<const CHUNK: usize>(
407 &self,
408 va: &[u64],
409 sb: &usize,
410 sc: &u64,
411 vd: &mut [u64],
412 );
413
414 // vec(d) <- vec(d) + (vec(a)>>scalar(b)) & scalar(c).
415 fn va_rsh_sb_mask_sc_add_vd_into_vd<const CHUNK: usize>(
416 &self,
417 va: &[u64],
418 sb: &usize,
419 sc: &u64,
420 vd: &mut [u64],
421 );
422
423 // vec(c) <- i-th unsigned digit base 2^{sb} of vec(a).
424 // vec(c) is ensured to be in the range [0, 2^{sb}-1[ with E[vec(c)] = 2^{sb}-1.
425 fn va_ith_digit_unsigned_base_sb_into_vc<const CHUNK: usize>(
426 &self,
427 i: usize,
428 va: &[u64],
429 sb: &usize,
430 vc: &mut [u64],
431 );
432
433 // vec(c) <- i-th signed digit base 2^{w} of vec(a).
434 // Reads the carry of the i-1-th iteration and write the carry on the i-th iteration on carry.
435 // if i > 0, carry of the i-1th iteration must be provided.
436 // if BALANCED: vec(c) is ensured to be [-2^{sb-1}, 2^{sb-1}[ with E[vec(c)] = 0, else E[vec(c)] = -0.5
437 fn va_ith_digit_signed_base_sb_into_vc<const CHUNK: usize, const BALANCED: bool>(
438 &self,
439 i: usize,
440 va: &[u64],
441 sb: &usize,
442 carry: &mut [u64],
443 vc: &mut [u64],
444 );
445}