Coverage Report

Created: 2026-02-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gmp/mpn/powlo.c
Line
Count
Source
1
/* mpn_powlo -- Compute R = U^E mod B^n, where B is the limb base.
2
3
Copyright 2007-2009, 2012, 2015, 2016, 2018, 2020 Free Software
4
Foundation, Inc.
5
6
This file is part of the GNU MP Library.
7
8
The GNU MP Library is free software; you can redistribute it and/or modify
9
it under the terms of either:
10
11
  * the GNU Lesser General Public License as published by the Free
12
    Software Foundation; either version 3 of the License, or (at your
13
    option) any later version.
14
15
or
16
17
  * the GNU General Public License as published by the Free Software
18
    Foundation; either version 2 of the License, or (at your option) any
19
    later version.
20
21
or both in parallel, as here.
22
23
The GNU MP Library is distributed in the hope that it will be useful, but
24
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
for more details.
27
28
You should have received copies of the GNU General Public License and the
29
GNU Lesser General Public License along with the GNU MP Library.  If not,
30
see https://www.gnu.org/licenses/.  */
31
32
33
#include "gmp-impl.h"
34
#include "longlong.h"
35
36
37
#define getbit(p,bi) \
38
436k
  ((p[(bi - 1) / GMP_LIMB_BITS] >> (bi - 1) % GMP_LIMB_BITS) & 1)
39
40
static inline mp_limb_t
41
getbits (const mp_limb_t *p, mp_bitcnt_t bi, unsigned nbits)
42
142k
{
43
142k
  unsigned nbits_in_r;
44
142k
  mp_limb_t r;
45
142k
  mp_size_t i;
46
47
142k
  if (bi <= nbits)
48
1.25k
    {
49
1.25k
      return p[0] & (((mp_limb_t) 1 << bi) - 1);
50
1.25k
    }
51
141k
  else
52
141k
    {
53
141k
      bi -= nbits;      /* bit index of low bit to extract */
54
141k
      i = bi / GMP_NUMB_BITS;   /* word index of low bit to extract */
55
141k
      bi %= GMP_NUMB_BITS;   /* bit index in low word */
56
141k
      r = p[i] >> bi;     /* extract (low) bits */
57
141k
      nbits_in_r = GMP_NUMB_BITS - bi;  /* number of bits now in r */
58
141k
      if (nbits_in_r < nbits)    /* did we get enough bits? */
59
7.70k
  r += p[i + 1] << nbits_in_r; /* prepend bits from higher word */
60
141k
      return r & (((mp_limb_t) 1 << nbits) - 1);
61
141k
    }
62
142k
}
63
64
static inline unsigned
65
win_size (mp_bitcnt_t eb)
66
2.44k
{
67
2.44k
  unsigned k;
68
2.44k
  static mp_bitcnt_t x[] = {7,25,81,241,673,1793,4609,11521,28161,~(mp_bitcnt_t)0};
69
2.44k
  ASSERT (eb > 1);
70
10.9k
  for (k = 0; eb > x[k++];)
71
8.47k
    ;
72
2.44k
  return k;
73
2.44k
}
74
75
/* rp[n-1..0] = bp[n-1..0] ^ ep[en-1..0] mod B^n, B is the limb base.
76
   Requires that ep[en-1] is non-zero.
77
   Uses scratch space tp[3n-1..0], i.e., 3n words.  */
78
/* We only use n words in the scratch space, we should pass tp + n to
79
   mullo/sqrlo as a temporary area, it is needed. */
80
void
81
mpn_powlo (mp_ptr rp, mp_srcptr bp,
82
     mp_srcptr ep, mp_size_t en,
83
     mp_size_t n, mp_ptr tp)
84
2.44k
{
85
2.44k
  unsigned cnt;
86
2.44k
  mp_bitcnt_t ebi;
87
2.44k
  unsigned windowsize, this_windowsize;
88
2.44k
  mp_limb_t expbits;
89
2.44k
  mp_limb_t *pp;
90
2.44k
  long i;
91
2.44k
  int flipflop;
92
2.44k
  TMP_DECL;
93
94
2.44k
  ASSERT (en > 1 || (en == 1 && ep[0] > 1));
95
96
2.44k
  TMP_MARK;
97
98
2.44k
  MPN_SIZEINBASE_2EXP(ebi, ep, en, 1);
99
100
2.44k
  windowsize = win_size (ebi);
101
2.44k
  if (windowsize > 1)
102
2.37k
    {
103
2.37k
      mp_limb_t *this_pp, *last_pp;
104
2.37k
      ASSERT (windowsize < ebi);
105
106
2.37k
      pp = TMP_ALLOC_LIMBS ((n << (windowsize - 1)));
107
108
2.37k
      this_pp = pp;
109
110
2.37k
      MPN_COPY (this_pp, bp, n);
111
112
      /* Store b^2 in tp.  */
113
2.37k
      mpn_sqrlo (tp, bp, n);
114
115
      /* Precompute odd powers of b and put them in the temporary area at pp.  */
116
2.37k
      i = (1 << (windowsize - 1)) - 1;
117
2.37k
      do
118
33.8k
  {
119
33.8k
    last_pp = this_pp;
120
33.8k
    this_pp += n;
121
33.8k
    mpn_mullo_n (this_pp, last_pp, tp, n);
122
33.8k
  } while (--i != 0);
123
124
2.37k
      expbits = getbits (ep, ebi, windowsize);
125
2.37k
      ebi -= windowsize;
126
127
      /* THINK: Should we initialise the case expbits % 4 == 0 with a mullo? */
128
2.37k
      count_trailing_zeros (cnt, expbits);
129
2.37k
      ebi += cnt;
130
2.37k
      expbits >>= cnt;
131
132
2.37k
      MPN_COPY (rp, pp + n * (expbits >> 1), n);
133
2.37k
    }
134
62
  else
135
62
    {
136
62
      pp = tp + n;
137
62
      MPN_COPY (pp, bp, n);
138
62
      MPN_COPY (rp, bp, n);
139
62
      --ebi;
140
62
    }
141
142
2.44k
  flipflop = 0;
143
144
2.44k
  do
145
142k
    {
146
436k
      while (getbit (ep, ebi) == 0)
147
295k
  {
148
295k
    mpn_sqrlo (tp, rp, n);
149
295k
    MP_PTR_SWAP (rp, tp);
150
295k
    flipflop = ! flipflop;
151
295k
    if (--ebi == 0)
152
1.99k
      goto done;
153
295k
  }
154
155
      /* The next bit of the exponent is 1.  Now extract the largest block of
156
   bits <= windowsize, and such that the least significant bit is 1.  */
157
158
140k
      expbits = getbits (ep, ebi, windowsize);
159
140k
      this_windowsize = MIN (windowsize, ebi);
160
161
140k
      count_trailing_zeros (cnt, expbits);
162
140k
      this_windowsize -= cnt;
163
140k
      ebi -= this_windowsize;
164
140k
      expbits >>= cnt;
165
166
400k
      while (this_windowsize > 1)
167
260k
  {
168
260k
    mpn_sqrlo (tp, rp, n);
169
260k
    mpn_sqrlo (rp, tp, n);
170
260k
    this_windowsize -= 2;
171
260k
  }
172
173
140k
      if (this_windowsize != 0)
174
73.6k
  mpn_sqrlo (tp, rp, n);
175
66.8k
      else
176
66.8k
  {
177
66.8k
    MP_PTR_SWAP (rp, tp);
178
66.8k
    flipflop = ! flipflop;
179
66.8k
  }
180
181
140k
      mpn_mullo_n (rp, tp, pp + n * (expbits >> 1), n);
182
140k
    } while (ebi != 0);
183
184
2.44k
 done:
185
2.44k
  if (flipflop)
186
1.55k
    MPN_COPY (tp, rp, n);
187
2.44k
  TMP_FREE;
188
2.44k
}