OSDN Git Service

ffc33a6b50e070c064ec2a7843b34ee101c292c7
[eos/base.git] / util / src / TclTk / tcl8.6.12 / libtommath / bn_mp_dr_reduce.c
1 #include "tommath_private.h"
2 #ifdef BN_MP_DR_REDUCE_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
5
6 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
7  *
8  * Based on algorithm from the paper
9  *
10  * "Generating Efficient Primes for Discrete Log Cryptosystems"
11  *                 Chae Hoon Lim, Pil Joong Lee,
12  *          POSTECH Information Research Laboratories
13  *
14  * The modulus must be of a special format [see manual]
15  *
16  * Has been modified to use algorithm 7.10 from the LTM book instead
17  *
18  * Input x must be in the range 0 <= x <= (n-1)**2
19  */
20 mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k)
21 {
22    mp_err      err;
23    int i, m;
24    mp_word  r;
25    mp_digit mu, *tmpx1, *tmpx2;
26
27    /* m = digits in modulus */
28    m = n->used;
29
30    /* ensure that "x" has at least 2m digits */
31    if (x->alloc < (m + m)) {
32       if ((err = mp_grow(x, m + m)) != MP_OKAY) {
33          return err;
34       }
35    }
36
37    /* top of loop, this is where the code resumes if
38     * another reduction pass is required.
39     */
40 top:
41    /* aliases for digits */
42    /* alias for lower half of x */
43    tmpx1 = x->dp;
44
45    /* alias for upper half of x, or x/B**m */
46    tmpx2 = x->dp + m;
47
48    /* set carry to zero */
49    mu = 0;
50
51    /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
52    for (i = 0; i < m; i++) {
53       r         = ((mp_word)*tmpx2++ * (mp_word)k) + *tmpx1 + mu;
54       *tmpx1++  = (mp_digit)(r & MP_MASK);
55       mu        = (mp_digit)(r >> ((mp_word)MP_DIGIT_BIT));
56    }
57
58    /* set final carry */
59    *tmpx1++ = mu;
60
61    /* zero words above m */
62    MP_ZERO_DIGITS(tmpx1, (x->used - m) - 1);
63
64    /* clamp, sub and return */
65    mp_clamp(x);
66
67    /* if x >= n then subtract and reduce again
68     * Each successive "recursion" makes the input smaller and smaller.
69     */
70    if (mp_cmp_mag(x, n) != MP_LT) {
71       if ((err = s_mp_sub(x, n, x)) != MP_OKAY) {
72          return err;
73       }
74       goto top;
75    }
76    return MP_OKAY;
77 }
78 #endif