Coverage Report

Created: 2025-04-11 06:45

/src/gmp-6.2.1/mpn/powm.c
Line
Count
Source (jump to first uncovered line)
1
/* mpn_powm -- Compute R = U^E mod M.
2
3
   Contributed to the GNU project by Torbjorn Granlund.
4
5
   THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES.  IT IS ONLY
6
   SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
7
   GUARANTEED THAT THEY WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
8
9
Copyright 2007-2012, 2019 Free Software Foundation, Inc.
10
11
This file is part of the GNU MP Library.
12
13
The GNU MP Library is free software; you can redistribute it and/or modify
14
it under the terms of either:
15
16
  * the GNU Lesser General Public License as published by the Free
17
    Software Foundation; either version 3 of the License, or (at your
18
    option) any later version.
19
20
or
21
22
  * the GNU General Public License as published by the Free Software
23
    Foundation; either version 2 of the License, or (at your option) any
24
    later version.
25
26
or both in parallel, as here.
27
28
The GNU MP Library is distributed in the hope that it will be useful, but
29
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
30
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
31
for more details.
32
33
You should have received copies of the GNU General Public License and the
34
GNU Lesser General Public License along with the GNU MP Library.  If not,
35
see https://www.gnu.org/licenses/.  */
36
37
38
/*
39
  BASIC ALGORITHM, Compute U^E mod M, where M < B^n is odd.
40
41
  1. W <- U
42
43
  2. T <- (B^n * U) mod M                Convert to REDC form
44
45
  3. Compute table U^1, U^3, U^5... of E-dependent size
46
47
  4. While there are more bits in E
48
       W <- power left-to-right base-k
49
50
51
  TODO:
52
53
   * Make getbits a macro, thereby allowing it to update the index operand.
54
     That will simplify the code using getbits.  (Perhaps make getbits' sibling
55
     getbit then have similar form, for symmetry.)
56
57
   * Write an itch function.  Or perhaps get rid of tp parameter since the huge
58
     pp area is allocated locally anyway?
59
60
   * Choose window size without looping.  (Superoptimize or think(tm).)
61
62
   * Handle small bases with initial, reduction-free exponentiation.
63
64
   * Call new division functions, not mpn_tdiv_qr.
65
66
   * Consider special code for one-limb M.
67
68
   * How should we handle the redc1/redc2/redc_n choice?
69
     - redc1:  T(binvert_1limb)  + e * (n)   * (T(mullo-1x1) + n*T(addmul_1))
70
     - redc2:  T(binvert_2limbs) + e * (n/2) * (T(mullo-2x2) + n*T(addmul_2))
71
     - redc_n: T(binvert_nlimbs) + e * (T(mullo-nxn) + T(M(n)))
72
     This disregards the addmul_N constant term, but we could think of
73
     that as part of the respective mullo.
74
75
   * When U (the base) is small, we should start the exponentiation with plain
76
     operations, then convert that partial result to REDC form.
77
78
   * When U is just one limb, should it be handled without the k-ary tricks?
79
     We could keep a factor of B^n in W, but use U' = BU as base.  After
80
     multiplying by this (pseudo two-limb) number, we need to multiply by 1/B
81
     mod M.
82
*/
83
84
#include "gmp-impl.h"
85
#include "longlong.h"
86
87
#undef MPN_REDC_0
88
#define MPN_REDC_0(rp, up, mp, invm)          \
89
320k
  do {                 \
90
320k
    mp_limb_t p1, r0, u0, _dummy;         \
91
320k
    u0 = *(up);               \
92
320k
    umul_ppmm (p1, _dummy, *(mp), (u0 * (invm)) & GMP_NUMB_MASK);  \
93
320k
    ASSERT (((u0 + _dummy) & GMP_NUMB_MASK) == 0);      \
94
320k
    p1 += (u0 != 0);              \
95
320k
    r0 = (up)[1] + p1;              \
96
320k
    if (p1 > r0)             \
97
320k
      r0 -= *(mp);             \
98
320k
    *(rp) = r0;               \
99
320k
  } while (0)
100
101
#undef MPN_REDC_1
102
#if HAVE_NATIVE_mpn_sbpi1_bdiv_r
103
#define MPN_REDC_1(rp, up, mp, n, invm)         \
104
  do {                  \
105
    mp_limb_t cy;             \
106
    cy = mpn_sbpi1_bdiv_r (up, 2 * n, mp, n, invm);     \
107
    if (cy != 0)              \
108
      mpn_sub_n (rp, up + n, mp, n);          \
109
    else                \
110
      MPN_COPY (rp, up + n, n);           \
111
  } while (0)
112
#else
113
#define MPN_REDC_1(rp, up, mp, n, invm)         \
114
357k
  do {                 \
115
357k
    mp_limb_t cy;             \
116
357k
    cy = mpn_redc_1 (rp, up, mp, n, invm);       \
117
357k
    if (cy != 0)             \
118
357k
      mpn_sub_n (rp, rp, mp, n);         \
119
357k
  } while (0)
120
#endif
121
122
#undef MPN_REDC_2
123
#define MPN_REDC_2(rp, up, mp, n, mip)          \
124
317k
  do {                 \
125
317k
    mp_limb_t cy;             \
126
317k
    cy = mpn_redc_2 (rp, up, mp, n, mip);        \
127
317k
    if (cy != 0)             \
128
317k
      mpn_sub_n (rp, rp, mp, n);         \
129
317k
  } while (0)
130
131
#if HAVE_NATIVE_mpn_addmul_2 || HAVE_NATIVE_mpn_redc_2
132
#define WANT_REDC_2 1
133
#endif
134
135
#define getbit(p,bi) \
136
1.24M
  ((p[(bi - 1) / GMP_LIMB_BITS] >> (bi - 1) % GMP_LIMB_BITS) & 1)
137
138
static inline mp_limb_t
139
getbits (const mp_limb_t *p, mp_bitcnt_t bi, int nbits)
140
390k
{
141
390k
  int nbits_in_r;
142
390k
  mp_limb_t r;
143
390k
  mp_size_t i;
144
145
390k
  if (bi < nbits)
146
1.24k
    {
147
1.24k
      return p[0] & (((mp_limb_t) 1 << bi) - 1);
148
1.24k
    }
149
389k
  else
150
389k
    {
151
389k
      bi -= nbits;      /* bit index of low bit to extract */
152
389k
      i = bi / GMP_NUMB_BITS;   /* word index of low bit to extract */
153
389k
      bi %= GMP_NUMB_BITS;   /* bit index in low word */
154
389k
      r = p[i] >> bi;     /* extract (low) bits */
155
389k
      nbits_in_r = GMP_NUMB_BITS - bi;  /* number of bits now in r */
156
389k
      if (nbits_in_r < nbits)    /* did we get enough bits? */
157
38.9k
  r += p[i + 1] << nbits_in_r; /* prepend bits from higher word */
158
389k
      return r & (((mp_limb_t) 1 << nbits) - 1);
159
389k
    }
160
390k
}
161
162
static inline int
163
win_size (mp_bitcnt_t eb)
164
2.68k
{
165
2.68k
  int k;
166
2.68k
  static mp_bitcnt_t x[] = {0,7,25,81,241,673,1793,4609,11521,28161,~(mp_bitcnt_t)0};
167
9.96k
  for (k = 1; eb > x[k]; k++)
168
7.28k
    ;
169
2.68k
  return k;
170
2.68k
}
171
172
/* Convert U to REDC form, U_r = B^n * U mod M */
173
static void
174
redcify (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr mp, mp_size_t n)
175
2.68k
{
176
2.68k
  mp_ptr tp, qp;
177
2.68k
  TMP_DECL;
178
2.68k
  TMP_MARK;
179
180
2.68k
  TMP_ALLOC_LIMBS_2 (tp, un + n, qp, un + 1);
181
182
2.68k
  MPN_ZERO (tp, n);
183
2.68k
  MPN_COPY (tp + n, up, un);
184
2.68k
  mpn_tdiv_qr (qp, rp, 0L, tp, un + n, mp, n);
185
2.68k
  TMP_FREE;
186
2.68k
}
187
188
/* rp[n-1..0] = bp[bn-1..0] ^ ep[en-1..0] mod mp[n-1..0]
189
   Requires that mp[n-1..0] is odd.
190
   Requires that ep[en-1..0] is > 1.
191
   Uses scratch space at tp of MAX(mpn_binvert_itch(n),2n) limbs.  */
192
void
193
mpn_powm (mp_ptr rp, mp_srcptr bp, mp_size_t bn,
194
    mp_srcptr ep, mp_size_t en,
195
    mp_srcptr mp, mp_size_t n, mp_ptr tp)
196
2.68k
{
197
2.68k
  mp_limb_t ip[2], *mip;
198
2.68k
  int cnt;
199
2.68k
  mp_bitcnt_t ebi;
200
2.68k
  int windowsize, this_windowsize;
201
2.68k
  mp_limb_t expbits;
202
2.68k
  mp_ptr pp, this_pp;
203
2.68k
  long i;
204
2.68k
  TMP_DECL;
205
206
2.68k
  ASSERT (en > 1 || (en == 1 && ep[0] > 1));
207
2.68k
  ASSERT (n >= 1 && ((mp[0] & 1) != 0));
208
209
2.68k
  TMP_MARK;
210
211
2.68k
  MPN_SIZEINBASE_2EXP(ebi, ep, en, 1);
212
213
#if 0
214
  if (bn < n)
215
    {
216
      /* Do the first few exponent bits without mod reductions,
217
   until the result is greater than the mod argument.  */
218
      for (;;)
219
  {
220
    mpn_sqr (tp, this_pp, tn);
221
    tn = tn * 2 - 1,  tn += tp[tn] != 0;
222
    if (getbit (ep, ebi) != 0)
223
      mpn_mul (..., tp, tn, bp, bn);
224
    ebi--;
225
  }
226
    }
227
#endif
228
229
2.68k
  windowsize = win_size (ebi);
230
231
2.68k
#if WANT_REDC_2
232
2.68k
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
233
1.34k
    {
234
1.34k
      mip = ip;
235
1.34k
      binvert_limb (mip[0], mp[0]);
236
1.34k
      mip[0] = -mip[0];
237
1.34k
    }
238
1.33k
  else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
239
303
    {
240
303
      mip = ip;
241
303
      mpn_binvert (mip, mp, 2, tp);
242
303
      mip[0] = -mip[0]; mip[1] = ~mip[1];
243
303
    }
244
#else
245
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
246
    {
247
      mip = ip;
248
      binvert_limb (mip[0], mp[0]);
249
      mip[0] = -mip[0];
250
    }
251
#endif
252
1.03k
  else
253
1.03k
    {
254
1.03k
      mip = TMP_ALLOC_LIMBS (n);
255
1.03k
      mpn_binvert (mip, mp, n, tp);
256
1.03k
    }
257
258
2.68k
  pp = TMP_ALLOC_LIMBS (n << (windowsize - 1));
259
260
2.68k
  this_pp = pp;
261
2.68k
  redcify (this_pp, bp, bn, mp, n);
262
263
  /* Store b^2 at rp.  */
264
2.68k
  mpn_sqr (tp, this_pp, n);
265
#if 0
266
  if (n == 1) {
267
    MPN_REDC_0 (rp, tp, mp, mip[0]);
268
  } else
269
#endif
270
2.68k
#if WANT_REDC_2
271
2.68k
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
272
1.34k
    MPN_REDC_1 (rp, tp, mp, n, mip[0]);
273
1.33k
  else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
274
303
    MPN_REDC_2 (rp, tp, mp, n, mip);
275
#else
276
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
277
    MPN_REDC_1 (rp, tp, mp, n, mip[0]);
278
#endif
279
1.03k
  else
280
1.03k
    mpn_redc_n (rp, tp, mp, n, mip);
281
282
  /* Precompute odd powers of b and put them in the temporary area at pp.  */
283
64.9k
  for (i = (1 << (windowsize - 1)) - 1; i > 0; i--)
284
62.2k
#if 1
285
62.2k
    if (n == 1) {
286
6.13k
      umul_ppmm((tp)[1], *(tp), *(this_pp), *(rp));
287
6.13k
      ++this_pp ;
288
6.13k
      MPN_REDC_0 (this_pp, tp, mp, mip[0]);
289
6.13k
    } else
290
56.1k
#endif
291
56.1k
    {
292
56.1k
      mpn_mul_n (tp, this_pp, rp, n);
293
56.1k
      this_pp += n;
294
56.1k
#if WANT_REDC_2
295
56.1k
      if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
296
7.61k
  MPN_REDC_1 (this_pp, tp, mp, n, mip[0]);
297
48.5k
      else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
298
5.89k
  MPN_REDC_2 (this_pp, tp, mp, n, mip);
299
#else
300
      if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
301
  MPN_REDC_1 (this_pp, tp, mp, n, mip[0]);
302
#endif
303
42.6k
      else
304
42.6k
  mpn_redc_n (this_pp, tp, mp, n, mip);
305
56.1k
    }
306
307
2.68k
  expbits = getbits (ep, ebi, windowsize);
308
2.68k
  if (ebi < windowsize)
309
0
    ebi = 0;
310
2.68k
  else
311
2.68k
    ebi -= windowsize;
312
313
2.68k
  count_trailing_zeros (cnt, expbits);
314
2.68k
  ebi += cnt;
315
2.68k
  expbits >>= cnt;
316
317
2.68k
  MPN_COPY (rp, pp + n * (expbits >> 1), n);
318
319
2.68k
#define INNERLOOP             \
320
390k
  while (ebi != 0)             \
321
389k
    {                 \
322
1.24M
      while (getbit (ep, ebi) == 0)         \
323
858k
  {               \
324
858k
    MPN_SQR (tp, rp, n);           \
325
858k
    MPN_REDUCE (rp, tp, mp, n, mip);        \
326
858k
    if (--ebi == 0)           \
327
81.2k
      goto done;             \
328
81.2k
  }                \
329
389k
                  \
330
      /* The next bit of the exponent is 1.  Now extract the largest  \
331
   block of bits <= windowsize, and such that the least   \
332
   significant bit is 1.  */          \
333
389k
                  \
334
389k
      expbits = getbits (ep, ebi, windowsize);        \
335
387k
      this_windowsize = windowsize;         \
336
387k
      if (ebi < windowsize)           \
337
387k
  {               \
338
1.24k
    this_windowsize -= windowsize - ebi;        \
339
1.24k
    ebi = 0;              \
340
1.24k
  }                \
341
387k
      else                \
342
387k
        ebi -= windowsize;           \
343
387k
                  \
344
387k
      count_trailing_zeros (cnt, expbits);        \
345
387k
      this_windowsize -= cnt;           \
346
387k
      ebi += cnt;             \
347
387k
      expbits >>= cnt;              \
348
387k
                  \
349
387k
      do                \
350
2.50M
  {               \
351
2.50M
    MPN_SQR (tp, rp, n);           \
352
2.50M
    MPN_REDUCE (rp, tp, mp, n, mip);        \
353
2.50M
  }                \
354
2.50M
      while (--this_windowsize != 0);          \
355
387k
                  \
356
387k
      MPN_MUL_N (tp, rp, pp + n * (expbits >> 1), n);      \
357
387k
      MPN_REDUCE (rp, tp, mp, n, mip);          \
358
32.5k
    }
359
360
361
2.68k
  if (n == 1)
362
429
    {
363
429
#undef MPN_MUL_N
364
429
#undef MPN_SQR
365
429
#undef MPN_REDUCE
366
32.5k
#define MPN_MUL_N(r,a,b,n)    umul_ppmm((r)[1], *(r), *(a), *(b))
367
281k
#define MPN_SQR(r,a,n)      umul_ppmm((r)[1], *(r), *(a), *(a))
368
314k
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_0(rp, tp, mp, mip[0])
369
429
      INNERLOOP;
370
234
    }
371
2.25k
  else
372
2.25k
#if WANT_REDC_2
373
2.25k
  if (REDC_1_TO_REDC_2_THRESHOLD < MUL_TOOM22_THRESHOLD)
374
0
    {
375
0
      if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
376
0
  {
377
0
    if (REDC_1_TO_REDC_2_THRESHOLD < SQR_BASECASE_THRESHOLD
378
0
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
379
0
      {
380
0
#undef MPN_MUL_N
381
0
#undef MPN_SQR
382
0
#undef MPN_REDUCE
383
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
384
0
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
385
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
386
0
        INNERLOOP;
387
0
      }
388
0
    else
389
0
      {
390
0
#undef MPN_MUL_N
391
0
#undef MPN_SQR
392
0
#undef MPN_REDUCE
393
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
394
0
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
395
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
396
0
        INNERLOOP;
397
0
      }
398
0
  }
399
0
      else if (BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD))
400
0
  {
401
0
    if (MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
402
0
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
403
0
      {
404
0
#undef MPN_MUL_N
405
0
#undef MPN_SQR
406
0
#undef MPN_REDUCE
407
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
408
0
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
409
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_2 (rp, tp, mp, n, mip)
410
0
        INNERLOOP;
411
0
      }
412
0
    else
413
0
      {
414
0
#undef MPN_MUL_N
415
0
#undef MPN_SQR
416
0
#undef MPN_REDUCE
417
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
418
0
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
419
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_2 (rp, tp, mp, n, mip)
420
0
        INNERLOOP;
421
0
      }
422
0
  }
423
0
      else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
424
0
  {
425
0
#undef MPN_MUL_N
426
0
#undef MPN_SQR
427
0
#undef MPN_REDUCE
428
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
429
0
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
430
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_2 (rp, tp, mp, n, mip)
431
0
    INNERLOOP;
432
0
  }
433
0
      else
434
0
  {
435
0
#undef MPN_MUL_N
436
0
#undef MPN_SQR
437
0
#undef MPN_REDUCE
438
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
439
0
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
440
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
441
0
    INNERLOOP;
442
0
  }
443
0
    }
444
2.25k
  else
445
2.25k
    {
446
2.25k
      if (BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD))
447
712
  {
448
712
    if (MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
449
712
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
450
0
      {
451
0
#undef MPN_MUL_N
452
0
#undef MPN_SQR
453
0
#undef MPN_REDUCE
454
0
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
455
0
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
456
0
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
457
0
        INNERLOOP;
458
0
      }
459
712
    else
460
712
      {
461
712
#undef MPN_MUL_N
462
712
#undef MPN_SQR
463
712
#undef MPN_REDUCE
464
30.2k
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
465
219k
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
466
249k
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
467
712
        INNERLOOP;
468
358
      }
469
712
  }
470
1.53k
      else if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
471
202
  {
472
202
#undef MPN_MUL_N
473
202
#undef MPN_SQR
474
202
#undef MPN_REDUCE
475
11.3k
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
476
86.1k
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
477
97.4k
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
478
202
    INNERLOOP;
479
62
  }
480
1.33k
      else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
481
303
  {
482
303
#undef MPN_MUL_N
483
303
#undef MPN_SQR
484
303
#undef MPN_REDUCE
485
33.8k
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
486
277k
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
487
311k
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_2 (rp, tp, mp, n, mip)
488
303
    INNERLOOP;
489
102
  }
490
1.03k
      else
491
1.03k
  {
492
1.03k
#undef MPN_MUL_N
493
1.03k
#undef MPN_SQR
494
1.03k
#undef MPN_REDUCE
495
279k
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
496
2.49M
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
497
2.77M
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
498
1.03k
    INNERLOOP;
499
265
  }
500
2.25k
    }
501
502
#else  /* WANT_REDC_2 */
503
504
  if (REDC_1_TO_REDC_N_THRESHOLD < MUL_TOOM22_THRESHOLD)
505
    {
506
      if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
507
  {
508
    if (REDC_1_TO_REDC_N_THRESHOLD < SQR_BASECASE_THRESHOLD
509
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
510
      {
511
#undef MPN_MUL_N
512
#undef MPN_SQR
513
#undef MPN_REDUCE
514
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
515
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
516
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
517
        INNERLOOP;
518
      }
519
    else
520
      {
521
#undef MPN_MUL_N
522
#undef MPN_SQR
523
#undef MPN_REDUCE
524
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
525
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
526
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
527
        INNERLOOP;
528
      }
529
  }
530
      else if (BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD))
531
  {
532
    if (MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
533
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
534
      {
535
#undef MPN_MUL_N
536
#undef MPN_SQR
537
#undef MPN_REDUCE
538
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
539
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
540
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
541
        INNERLOOP;
542
      }
543
    else
544
      {
545
#undef MPN_MUL_N
546
#undef MPN_SQR
547
#undef MPN_REDUCE
548
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
549
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
550
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
551
        INNERLOOP;
552
      }
553
  }
554
      else
555
  {
556
#undef MPN_MUL_N
557
#undef MPN_SQR
558
#undef MPN_REDUCE
559
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
560
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
561
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
562
    INNERLOOP;
563
  }
564
    }
565
  else
566
    {
567
      if (BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD))
568
  {
569
    if (MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD
570
        || BELOW_THRESHOLD (n, SQR_BASECASE_THRESHOLD))
571
      {
572
#undef MPN_MUL_N
573
#undef MPN_SQR
574
#undef MPN_REDUCE
575
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
576
#define MPN_SQR(r,a,n)      mpn_mul_basecase (r,a,n,a,n)
577
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
578
        INNERLOOP;
579
      }
580
    else
581
      {
582
#undef MPN_MUL_N
583
#undef MPN_SQR
584
#undef MPN_REDUCE
585
#define MPN_MUL_N(r,a,b,n)    mpn_mul_basecase (r,a,n,b,n)
586
#define MPN_SQR(r,a,n)      mpn_sqr_basecase (r,a,n)
587
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
588
        INNERLOOP;
589
      }
590
  }
591
      else if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
592
  {
593
#undef MPN_MUL_N
594
#undef MPN_SQR
595
#undef MPN_REDUCE
596
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
597
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
598
#define MPN_REDUCE(rp,tp,mp,n,mip)  MPN_REDC_1 (rp, tp, mp, n, mip[0])
599
    INNERLOOP;
600
  }
601
      else
602
  {
603
#undef MPN_MUL_N
604
#undef MPN_SQR
605
#undef MPN_REDUCE
606
#define MPN_MUL_N(r,a,b,n)    mpn_mul_n (r,a,b,n)
607
#define MPN_SQR(r,a,n)      mpn_sqr (r,a,n)
608
#define MPN_REDUCE(rp,tp,mp,n,mip)  mpn_redc_n (rp, tp, mp, n, mip)
609
    INNERLOOP;
610
  }
611
    }
612
#endif  /* WANT_REDC_2 */
613
614
2.68k
 done:
615
616
2.68k
  MPN_COPY (tp, rp, n);
617
2.68k
  MPN_ZERO (tp + n, n);
618
619
2.68k
#if WANT_REDC_2
620
2.68k
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_2_THRESHOLD))
621
1.34k
    MPN_REDC_1 (rp, tp, mp, n, mip[0]);
622
1.33k
  else if (BELOW_THRESHOLD (n, REDC_2_TO_REDC_N_THRESHOLD))
623
303
    MPN_REDC_2 (rp, tp, mp, n, mip);
624
#else
625
  if (BELOW_THRESHOLD (n, REDC_1_TO_REDC_N_THRESHOLD))
626
    MPN_REDC_1 (rp, tp, mp, n, mip[0]);
627
#endif
628
1.03k
  else
629
1.03k
    mpn_redc_n (rp, tp, mp, n, mip);
630
631
2.68k
  if (mpn_cmp (rp, mp, n) >= 0)
632
27
    mpn_sub_n (rp, rp, mp, n);
633
634
2.68k
  TMP_FREE;
635
2.68k
}