crypto_bigint/uint/modular/
reduction.rs1use crate::{Limb, Uint, WideWord, Word};
2
3#[inline(always)]
5const fn muladdcarry(x: Word, y: Word, z: Word, w: Word) -> (Word, Word) {
6 let res = (x as WideWord)
7 .wrapping_mul(y as WideWord)
8 .wrapping_add(z as WideWord)
9 .wrapping_add(w as WideWord);
10 ((res >> Word::BITS) as Word, res as Word)
11}
12
13pub const fn montgomery_reduction<const LIMBS: usize>(
15 lower_upper: &(Uint<LIMBS>, Uint<LIMBS>),
16 modulus: &Uint<LIMBS>,
17 mod_neg_inv: Limb,
18) -> Uint<LIMBS> {
19 let (mut lower, mut upper) = *lower_upper;
20
21 let mut meta_carry = Limb(0);
22 let mut new_sum;
23
24 let mut i = 0;
25 while i < LIMBS {
26 let u = lower.limbs[i].0.wrapping_mul(mod_neg_inv.0);
27
28 let (mut carry, _) = muladdcarry(u, modulus.limbs[0].0, lower.limbs[i].0, 0);
29 let mut new_limb;
30
31 let mut j = 1;
32 while j < (LIMBS - i) {
33 (carry, new_limb) = muladdcarry(u, modulus.limbs[j].0, lower.limbs[i + j].0, carry);
34 lower.limbs[i + j] = Limb(new_limb);
35 j += 1;
36 }
37 while j < LIMBS {
38 (carry, new_limb) =
39 muladdcarry(u, modulus.limbs[j].0, upper.limbs[i + j - LIMBS].0, carry);
40 upper.limbs[i + j - LIMBS] = Limb(new_limb);
41 j += 1;
42 }
43
44 (new_sum, meta_carry) = upper.limbs[i].adc(Limb(carry), meta_carry);
45 upper.limbs[i] = new_sum;
46
47 i += 1;
48 }
49
50 upper.sub_mod_with_carry(meta_carry, modulus, modulus)
55}