Merge pull request #578 from PX4/fix_mp_prime_strong_lucas_lefridge_compilation
[libtommath.git] / mp_montgomery_setup.c
blobde57dc342281866a78a648754e0504ab8349e02c
1 #include "tommath_private.h"
2 #ifdef MP_MONTGOMERY_SETUP_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
6 /* setups the montgomery reduction stuff */
7 mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho)
9 mp_digit x, b;
11 /* fast inversion mod 2**k
13 * Based on the fact that
15 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
16 * => 2*X*A - X*X*A*A = 1
17 * => 2*(1) - (1) = 1
19 b = n->dp[0];
21 if ((b & 1u) == 0u) {
22 return MP_VAL;
25 x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */
26 x *= 2u - (b * x); /* here x*a==1 mod 2**8 */
27 x *= 2u - (b * x); /* here x*a==1 mod 2**16 */
28 #if defined(MP_64BIT) || !(defined(MP_16BIT))
29 x *= 2u - (b * x); /* here x*a==1 mod 2**32 */
30 #endif
31 #ifdef MP_64BIT
32 x *= 2u - (b * x); /* here x*a==1 mod 2**64 */
33 #endif
35 /* rho = -1/m mod b */
36 *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK;
38 return MP_OKAY;
40 #endif