poulpy/math/src/modulus.rs
math/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 to b.
118 fn sa_mul_sb_montgomery_into_sa<const REDUCE: REDUCEMOD>(
119 &self,
120 b: &montgomery::Montgomery<O>,
121 a: &mut O,
122 );
123
124 // Assigns a * b to c.
125 fn sa_mul_sb_barrett_into_sc<const REDUCE: REDUCEMOD>(
126 &self,
127 a: &O,
128 b: &barrett::Barrett<O>,
129 c: &mut O,
130 );
131
132 // Assigns a * b to a.
133 fn sa_mul_sb_barrett_into_sa<const REDUCE: REDUCEMOD>(
134 &self,
135 b: &barrett::Barrett<O>,
136 a: &mut O,
137 );
138
139 // Assigns (a + q - b) * c to d.
140 fn sa_sub_sb_mul_sc_barrett_into_sd<const VBRANGE: u8, const REDUCE: REDUCEMOD>(
141 &self,
142 a: &O,
143 b: &O,
144 c: &barrett::Barrett<O>,
145 d: &mut O,
146 );
147
148 // Assigns (a + q - b) * c to b.
149 fn sa_sub_sb_mul_sc_barrett_into_sb<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
150 &self,
151 a: &u64,
152 c: &barrett::Barrett<u64>,
153 b: &mut u64,
154 );
155
156 // Assigns (a + b) * c to a.
157 fn sa_add_sb_mul_sc_barrett_into_sa<const REDUCE: REDUCEMOD>(
158 &self,
159 b: &u64,
160 c: &barrett::Barrett<u64>,
161 a: &mut u64,
162 );
163
164 // Assigns (a + b) * c to d.
165 fn sa_add_sb_mul_sc_barrett_into_sd<const REDUCE: REDUCEMOD>(
166 &self,
167 a: &u64,
168 b: &u64,
169 c: &barrett::Barrett<u64>,
170 d: &mut u64,
171 );
172
173 // Assigns (a - b + c) * d to e.
174 fn sb_sub_sa_add_sc_mul_sd_barrett_into_se<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
175 &self,
176 a: &u64,
177 b: &u64,
178 c: &u64,
179 d: &barrett::Barrett<u64>,
180 e: &mut u64,
181 );
182
183 fn sb_sub_sa_add_sc_mul_sd_barrett_into_sa<const SBRANGE: u8, const REDUCE: REDUCEMOD>(
184 &self,
185 b: &u64,
186 c: &u64,
187 d: &barrett::Barrett<u64>,
188 a: &mut u64,
189 );
190
191 fn sa_rsh_sb_mask_sc_into_sa(&self, c: &usize, b: &u64, a: &mut u64);
192
193 fn sa_rsh_sb_mask_sc_into_sd(&self, a: &u64, b: &usize, c: &u64, d: &mut u64);
194
195 fn sa_rsh_sb_mask_sc_add_sd_into_sd(&self, a: &u64, b: &usize, c: &u64, d: &mut u64);
196
197 fn sa_signed_digit_into_sb<const CARRYOVERWRITE: bool, const BALANCED: bool>(
198 &self,
199 a: &u64,
200 base: &u64,
201 shift: &usize,
202 mask: &u64,
203 carry: &mut u64,
204 b: &mut u64,
205 );
206}
207
208pub trait VectorOperations<O> {
209 // Applies a parameterized modular reduction.
210 fn va_reduce_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, x: &mut [O]);
211
212 // ADD
213 // vec(c) <- vec(a) + vec(b).
214 fn va_add_vb_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
215 &self,
216 va: &[O],
217 vb: &[O],
218 vc: &mut [O],
219 );
220
221 // vec(b) <- vec(a) + vec(b).
222 fn va_add_vb_into_vb<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, a: &[O], b: &mut [O]);
223
224 // vec(c) <- vec(a) + scalar(b).
225 fn va_add_sb_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
226 &self,
227 a: &[O],
228 b: &O,
229 c: &mut [O],
230 );
231
232 // vec(b) <- vec(b) + scalar(a).
233 fn va_add_sb_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(&self, a: &O, b: &mut [O]);
234
235 // vec(b) <- vec(a) - vec(b).
236 fn va_sub_vb_into_vb<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
237 &self,
238 a: &[O],
239 b: &mut [O],
240 );
241
242 // vec(a) <- vec(a) - vec(b).
243 fn va_sub_vb_into_va<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
244 &self,
245 b: &[O],
246 a: &mut [O],
247 );
248
249 // vec(c) <- vec(a) - vec(b).
250 fn va_sub_vb_into_vc<const CHUNK: usize, const VBRANGE: u8, const REDUCE: REDUCEMOD>(
251 &self,
252 a: &[O],
253 b: &[O],
254 c: &mut [O],
255 );
256
257 // vec(a) <- -vec(a).
258 fn va_neg_into_va<const CHUNK: usize, const VARANGE: u8, const REDUCE: REDUCEMOD>(
259 &self,
260 a: &mut [O],
261 );
262
263 // vec(b) <- -vec(a).
264 fn va_neg_into_vb<const CHUNK: usize, const VARANGE: u8, const REDUCE: REDUCEMOD>(
265 &self,
266 a: &[O],
267 b: &mut [O],
268 );
269
270 // vec(b) <- vec(a)
271 fn va_prep_mont_into_vb<const CHUNK: usize, const REDUCE: REDUCEMOD>(
272 &self,
273 a: &[O],
274 b: &mut [montgomery::Montgomery<O>],
275 );
276
277 // vec(a) <- vec(a).
278 fn va_prepare_montgomery_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
279 &self,
280 a: &mut [montgomery::Montgomery<O>],
281 );
282
283 // vec(c) <- vec(a) * vec(b).
284 fn va_mul_vb_montgomery_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
285 &self,
286 a: &[O],
287 b: &[montgomery::Montgomery<O>],
288 c: &mut [O],
289 );
290
291 // vec(a) <- vec(a) * vec(b).
292 fn va_mul_vb_montgomery_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
293 &self,
294 b: &[montgomery::Montgomery<O>],
295 a: &mut [O],
296 );
297
298 // vec(b) <- vec(a) * scalar(b).
299 fn va_mul_sb_barrett_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
300 &self,
301 b: &barrett::Barrett<u64>,
302 a: &mut [u64],
303 );
304
305 // vec(c) <- vec(a) * scalar(b).
306 fn va_mul_sb_barrett_into_vc<const CHUNK: usize, const REDUCE: REDUCEMOD>(
307 &self,
308 a: &[u64],
309 b: &barrett::Barrett<u64>,
310 c: &mut [u64],
311 );
312
313 // vec(d) <- (vec(a) + VBRANGE * q - vec(b)) * scalar(c).
314 fn va_sub_vb_mul_sc_barrett_into_vd<
315 const CHUNK: usize,
316 const VBRANGE: u8,
317 const REDUCE: REDUCEMOD,
318 >(
319 &self,
320 a: &[u64],
321 b: &[u64],
322 c: &barrett::Barrett<u64>,
323 d: &mut [u64],
324 );
325
326 // vec(b) <- (vec(a) + VBRANGE * q - vec(b)) * scalar(c).
327 fn va_sub_vb_mul_sc_barrett_into_vb<
328 const CHUNK: usize,
329 const VBRANGE: u8,
330 const REDUCE: REDUCEMOD,
331 >(
332 &self,
333 a: &[u64],
334 c: &barrett::Barrett<u64>,
335 b: &mut [u64],
336 );
337
338 // vec(c) <- (vec(a) + scalar(b)) * scalar(c).
339 fn va_add_sb_mul_sc_barrett_into_vd<const CHUNK: usize, const REDUCE: REDUCEMOD>(
340 &self,
341 va: &[u64],
342 sb: &u64,
343 sc: &barrett::Barrett<u64>,
344 vd: &mut [u64],
345 );
346
347 // vec(a) <- (vec(a) + scalar(b)) * scalar(c).
348 fn va_add_sb_mul_sc_barrett_into_va<const CHUNK: usize, const REDUCE: REDUCEMOD>(
349 &self,
350 sb: &u64,
351 sc: &barrett::Barrett<u64>,
352 va: &mut [u64],
353 );
354
355 // vec(e) <- (vec(b) - vec(a) + scalar(c)) * scalar(e).
356 fn vb_sub_va_add_sc_mul_sd_barrett_into_ve<
357 const CHUNK: usize,
358 const VBRANGE: u8,
359 const REDUCE: REDUCEMOD,
360 >(
361 &self,
362 va: &[u64],
363 vb: &[u64],
364 sc: &u64,
365 sd: &barrett::Barrett<u64>,
366 ve: &mut [u64],
367 );
368
369 // vec(a) <- (vec(b) - vec(a) + scalar(c)) * scalar(e).
370 fn vb_sub_va_add_sc_mul_sd_barrett_into_va<
371 const CHUNK: usize,
372 const VBRANGE: u8,
373 const REDUCE: REDUCEMOD,
374 >(
375 &self,
376 vb: &[u64],
377 sc: &u64,
378 sd: &barrett::Barrett<u64>,
379 va: &mut [u64],
380 );
381
382 // vec(a) <- (vec(a)>>scalar(b)) & scalar(c).
383 fn va_rsh_sb_mask_sc_into_va<const CHUNK: usize>(&self, sb: &usize, sc: &u64, va: &mut [u64]);
384
385 // vec(d) <- (vec(a)>>scalar(b)) & scalar(c).
386 fn va_rsh_sb_mask_sc_into_vd<const CHUNK: usize>(
387 &self,
388 va: &[u64],
389 sb: &usize,
390 sc: &u64,
391 vd: &mut [u64],
392 );
393
394 // vec(d) <- vec(d) + (vec(a)>>scalar(b)) & scalar(c).
395 fn va_rsh_sb_mask_sc_add_vd_into_vd<const CHUNK: usize>(
396 &self,
397 va: &[u64],
398 sb: &usize,
399 sc: &u64,
400 vd: &mut [u64],
401 );
402
403 // vec(c) <- i-th unsigned digit base 2^{sb} of vec(a).
404 // vec(c) is ensured to be in the range [0, 2^{sb}-1[ with E[vec(c)] = 2^{sb}-1.
405 fn va_ith_digit_unsigned_base_sb_into_vc<const CHUNK: usize>(
406 &self,
407 i: usize,
408 va: &[u64],
409 sb: &usize,
410 vc: &mut [u64],
411 );
412
413 // vec(c) <- i-th signed digit base 2^{w} of vec(a).
414 // Reads the carry of the i-1-th iteration and write the carry on the i-th iteration on carry.
415 // if i > 0, carry of the i-1th iteration must be provided.
416 // 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
417 fn va_ith_digit_signed_base_sb_into_vc<const CHUNK: usize, const BALANCED: bool>(
418 &self,
419 i: usize,
420 va: &[u64],
421 sb: &usize,
422 carry: &mut [u64],
423 vc: &mut [u64],
424 );
425}